cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

8250_aspeed_vuart.c (16017B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 *  Serial Port driver for Aspeed VUART device
      4 *
      5 *    Copyright (C) 2016 Jeremy Kerr <jk@ozlabs.org>, IBM Corp.
      6 *    Copyright (C) 2006 Arnd Bergmann <arnd@arndb.de>, IBM Corp.
      7 */
      8#include <linux/device.h>
      9#include <linux/module.h>
     10#include <linux/of_address.h>
     11#include <linux/of_irq.h>
     12#include <linux/of_platform.h>
     13#include <linux/regmap.h>
     14#include <linux/mfd/syscon.h>
     15#include <linux/tty.h>
     16#include <linux/tty_flip.h>
     17#include <linux/clk.h>
     18
     19#include "8250.h"
     20
     21#define ASPEED_VUART_GCRA		0x20
     22#define ASPEED_VUART_GCRA_VUART_EN		BIT(0)
     23#define ASPEED_VUART_GCRA_HOST_SIRQ_POLARITY	BIT(1)
     24#define ASPEED_VUART_GCRA_DISABLE_HOST_TX_DISCARD BIT(5)
     25#define ASPEED_VUART_GCRB		0x24
     26#define ASPEED_VUART_GCRB_HOST_SIRQ_MASK	GENMASK(7, 4)
     27#define ASPEED_VUART_GCRB_HOST_SIRQ_SHIFT	4
     28#define ASPEED_VUART_ADDRL		0x28
     29#define ASPEED_VUART_ADDRH		0x2c
     30
     31#define ASPEED_VUART_DEFAULT_LPC_ADDR	0x3f8
     32#define ASPEED_VUART_DEFAULT_SIRQ	4
     33#define ASPEED_VUART_DEFAULT_SIRQ_POLARITY	IRQ_TYPE_LEVEL_LOW
     34
     35struct aspeed_vuart {
     36	struct device		*dev;
     37	struct clk		*clk;
     38	int			line;
     39	struct timer_list	unthrottle_timer;
     40	struct uart_8250_port	*port;
     41};
     42
     43/*
     44 * If we fill the tty flip buffers, we throttle the data ready interrupt
     45 * to prevent dropped characters. This timeout defines how long we wait
     46 * to (conditionally, depending on buffer state) unthrottle.
     47 */
     48static const int unthrottle_timeout = HZ/10;
     49
     50/*
     51 * The VUART is basically two UART 'front ends' connected by their FIFO
     52 * (no actual serial line in between). One is on the BMC side (management
     53 * controller) and one is on the host CPU side.
     54 *
     55 * It allows the BMC to provide to the host a "UART" that pipes into
     56 * the BMC itself and can then be turned by the BMC into a network console
     57 * of some sort for example.
     58 *
     59 * This driver is for the BMC side. The sysfs files allow the BMC
     60 * userspace which owns the system configuration policy, to specify
     61 * at what IO port and interrupt number the host side will appear
     62 * to the host on the Host <-> BMC LPC bus. It could be different on a
     63 * different system (though most of them use 3f8/4).
     64 */
     65
     66static inline u8 aspeed_vuart_readb(struct aspeed_vuart *vuart, u8 reg)
     67{
     68	return readb(vuart->port->port.membase + reg);
     69}
     70
     71static inline void aspeed_vuart_writeb(struct aspeed_vuart *vuart, u8 val, u8 reg)
     72{
     73	writeb(val, vuart->port->port.membase + reg);
     74}
     75
     76static ssize_t lpc_address_show(struct device *dev,
     77				struct device_attribute *attr, char *buf)
     78{
     79	struct aspeed_vuart *vuart = dev_get_drvdata(dev);
     80	u16 addr;
     81
     82	addr = (aspeed_vuart_readb(vuart, ASPEED_VUART_ADDRH) << 8) |
     83		(aspeed_vuart_readb(vuart, ASPEED_VUART_ADDRL));
     84
     85	return sysfs_emit(buf, "0x%x\n", addr);
     86}
     87
     88static int aspeed_vuart_set_lpc_address(struct aspeed_vuart *vuart, u32 addr)
     89{
     90	if (addr > U16_MAX)
     91		return -EINVAL;
     92
     93	aspeed_vuart_writeb(vuart, addr >> 8, ASPEED_VUART_ADDRH);
     94	aspeed_vuart_writeb(vuart, addr >> 0, ASPEED_VUART_ADDRL);
     95
     96	return 0;
     97}
     98
     99static ssize_t lpc_address_store(struct device *dev,
    100				 struct device_attribute *attr,
    101				 const char *buf, size_t count)
    102{
    103	struct aspeed_vuart *vuart = dev_get_drvdata(dev);
    104	u32 val;
    105	int err;
    106
    107	err = kstrtou32(buf, 0, &val);
    108	if (err)
    109		return err;
    110
    111	err = aspeed_vuart_set_lpc_address(vuart, val);
    112	return err ? : count;
    113}
    114
    115static DEVICE_ATTR_RW(lpc_address);
    116
    117static ssize_t sirq_show(struct device *dev,
    118			 struct device_attribute *attr, char *buf)
    119{
    120	struct aspeed_vuart *vuart = dev_get_drvdata(dev);
    121	u8 reg;
    122
    123	reg = aspeed_vuart_readb(vuart, ASPEED_VUART_GCRB);
    124	reg &= ASPEED_VUART_GCRB_HOST_SIRQ_MASK;
    125	reg >>= ASPEED_VUART_GCRB_HOST_SIRQ_SHIFT;
    126
    127	return sysfs_emit(buf, "%u\n", reg);
    128}
    129
    130static int aspeed_vuart_set_sirq(struct aspeed_vuart *vuart, u32 sirq)
    131{
    132	u8 reg;
    133
    134	if (sirq > (ASPEED_VUART_GCRB_HOST_SIRQ_MASK >> ASPEED_VUART_GCRB_HOST_SIRQ_SHIFT))
    135		return -EINVAL;
    136
    137	sirq <<= ASPEED_VUART_GCRB_HOST_SIRQ_SHIFT;
    138	sirq &= ASPEED_VUART_GCRB_HOST_SIRQ_MASK;
    139
    140	reg = aspeed_vuart_readb(vuart, ASPEED_VUART_GCRB);
    141	reg &= ~ASPEED_VUART_GCRB_HOST_SIRQ_MASK;
    142	reg |= sirq;
    143	aspeed_vuart_writeb(vuart, reg, ASPEED_VUART_GCRB);
    144
    145	return 0;
    146}
    147
    148static ssize_t sirq_store(struct device *dev, struct device_attribute *attr,
    149			  const char *buf, size_t count)
    150{
    151	struct aspeed_vuart *vuart = dev_get_drvdata(dev);
    152	unsigned long val;
    153	int err;
    154
    155	err = kstrtoul(buf, 0, &val);
    156	if (err)
    157		return err;
    158
    159	err = aspeed_vuart_set_sirq(vuart, val);
    160	return err ? : count;
    161}
    162
    163static DEVICE_ATTR_RW(sirq);
    164
    165static ssize_t sirq_polarity_show(struct device *dev,
    166				  struct device_attribute *attr, char *buf)
    167{
    168	struct aspeed_vuart *vuart = dev_get_drvdata(dev);
    169	u8 reg;
    170
    171	reg = aspeed_vuart_readb(vuart, ASPEED_VUART_GCRA);
    172	reg &= ASPEED_VUART_GCRA_HOST_SIRQ_POLARITY;
    173
    174	return sysfs_emit(buf, "%u\n", reg ? 1 : 0);
    175}
    176
    177static void aspeed_vuart_set_sirq_polarity(struct aspeed_vuart *vuart,
    178					   bool polarity)
    179{
    180	u8 reg = aspeed_vuart_readb(vuart, ASPEED_VUART_GCRA);
    181
    182	if (polarity)
    183		reg |= ASPEED_VUART_GCRA_HOST_SIRQ_POLARITY;
    184	else
    185		reg &= ~ASPEED_VUART_GCRA_HOST_SIRQ_POLARITY;
    186
    187	aspeed_vuart_writeb(vuart, reg, ASPEED_VUART_GCRA);
    188}
    189
    190static ssize_t sirq_polarity_store(struct device *dev,
    191				   struct device_attribute *attr,
    192				   const char *buf, size_t count)
    193{
    194	struct aspeed_vuart *vuart = dev_get_drvdata(dev);
    195	unsigned long val;
    196	int err;
    197
    198	err = kstrtoul(buf, 0, &val);
    199	if (err)
    200		return err;
    201
    202	aspeed_vuart_set_sirq_polarity(vuart, val != 0);
    203
    204	return count;
    205}
    206
    207static DEVICE_ATTR_RW(sirq_polarity);
    208
    209static struct attribute *aspeed_vuart_attrs[] = {
    210	&dev_attr_sirq.attr,
    211	&dev_attr_sirq_polarity.attr,
    212	&dev_attr_lpc_address.attr,
    213	NULL,
    214};
    215
    216static const struct attribute_group aspeed_vuart_attr_group = {
    217	.attrs = aspeed_vuart_attrs,
    218};
    219
    220static void aspeed_vuart_set_enabled(struct aspeed_vuart *vuart, bool enabled)
    221{
    222	u8 reg = aspeed_vuart_readb(vuart, ASPEED_VUART_GCRA);
    223
    224	if (enabled)
    225		reg |= ASPEED_VUART_GCRA_VUART_EN;
    226	else
    227		reg &= ~ASPEED_VUART_GCRA_VUART_EN;
    228
    229	aspeed_vuart_writeb(vuart, reg, ASPEED_VUART_GCRA);
    230}
    231
    232static void aspeed_vuart_set_host_tx_discard(struct aspeed_vuart *vuart,
    233					     bool discard)
    234{
    235	u8 reg;
    236
    237	reg = aspeed_vuart_readb(vuart, ASPEED_VUART_GCRA);
    238
    239	/* If the DISABLE_HOST_TX_DISCARD bit is set, discard is disabled */
    240	if (!discard)
    241		reg |= ASPEED_VUART_GCRA_DISABLE_HOST_TX_DISCARD;
    242	else
    243		reg &= ~ASPEED_VUART_GCRA_DISABLE_HOST_TX_DISCARD;
    244
    245	aspeed_vuart_writeb(vuart, reg, ASPEED_VUART_GCRA);
    246}
    247
    248static int aspeed_vuart_startup(struct uart_port *uart_port)
    249{
    250	struct uart_8250_port *uart_8250_port = up_to_u8250p(uart_port);
    251	struct aspeed_vuart *vuart = uart_8250_port->port.private_data;
    252	int rc;
    253
    254	rc = serial8250_do_startup(uart_port);
    255	if (rc)
    256		return rc;
    257
    258	aspeed_vuart_set_host_tx_discard(vuart, false);
    259
    260	return 0;
    261}
    262
    263static void aspeed_vuart_shutdown(struct uart_port *uart_port)
    264{
    265	struct uart_8250_port *uart_8250_port = up_to_u8250p(uart_port);
    266	struct aspeed_vuart *vuart = uart_8250_port->port.private_data;
    267
    268	aspeed_vuart_set_host_tx_discard(vuart, true);
    269
    270	serial8250_do_shutdown(uart_port);
    271}
    272
    273static void __aspeed_vuart_set_throttle(struct uart_8250_port *up,
    274		bool throttle)
    275{
    276	unsigned char irqs = UART_IER_RLSI | UART_IER_RDI;
    277
    278	up->ier &= ~irqs;
    279	if (!throttle)
    280		up->ier |= irqs;
    281	serial_out(up, UART_IER, up->ier);
    282}
    283static void aspeed_vuart_set_throttle(struct uart_port *port, bool throttle)
    284{
    285	struct uart_8250_port *up = up_to_u8250p(port);
    286	unsigned long flags;
    287
    288	spin_lock_irqsave(&port->lock, flags);
    289	__aspeed_vuart_set_throttle(up, throttle);
    290	spin_unlock_irqrestore(&port->lock, flags);
    291}
    292
    293static void aspeed_vuart_throttle(struct uart_port *port)
    294{
    295	aspeed_vuart_set_throttle(port, true);
    296}
    297
    298static void aspeed_vuart_unthrottle(struct uart_port *port)
    299{
    300	aspeed_vuart_set_throttle(port, false);
    301}
    302
    303static void aspeed_vuart_unthrottle_exp(struct timer_list *timer)
    304{
    305	struct aspeed_vuart *vuart = from_timer(vuart, timer, unthrottle_timer);
    306	struct uart_8250_port *up = vuart->port;
    307
    308	if (!tty_buffer_space_avail(&up->port.state->port)) {
    309		mod_timer(&vuart->unthrottle_timer,
    310			  jiffies + unthrottle_timeout);
    311		return;
    312	}
    313
    314	aspeed_vuart_unthrottle(&up->port);
    315}
    316
    317/*
    318 * Custom interrupt handler to manage finer-grained flow control. Although we
    319 * have throttle/unthrottle callbacks, we've seen that the VUART device can
    320 * deliver characters faster than the ldisc has a chance to check buffer space
    321 * against the throttle threshold. This results in dropped characters before
    322 * the throttle.
    323 *
    324 * We do this by checking for flip buffer space before RX. If we have no space,
    325 * throttle now and schedule an unthrottle for later, once the ldisc has had
    326 * a chance to drain the buffers.
    327 */
    328static int aspeed_vuart_handle_irq(struct uart_port *port)
    329{
    330	struct uart_8250_port *up = up_to_u8250p(port);
    331	unsigned int iir, lsr;
    332	unsigned long flags;
    333	unsigned int space, count;
    334
    335	iir = serial_port_in(port, UART_IIR);
    336
    337	if (iir & UART_IIR_NO_INT)
    338		return 0;
    339
    340	spin_lock_irqsave(&port->lock, flags);
    341
    342	lsr = serial_port_in(port, UART_LSR);
    343
    344	if (lsr & (UART_LSR_DR | UART_LSR_BI)) {
    345		space = tty_buffer_space_avail(&port->state->port);
    346
    347		if (!space) {
    348			/* throttle and schedule an unthrottle later */
    349			struct aspeed_vuart *vuart = port->private_data;
    350			__aspeed_vuart_set_throttle(up, true);
    351
    352			if (!timer_pending(&vuart->unthrottle_timer))
    353				mod_timer(&vuart->unthrottle_timer,
    354					  jiffies + unthrottle_timeout);
    355
    356		} else {
    357			count = min(space, 256U);
    358
    359			do {
    360				serial8250_read_char(up, lsr);
    361				lsr = serial_in(up, UART_LSR);
    362				if (--count == 0)
    363					break;
    364			} while (lsr & (UART_LSR_DR | UART_LSR_BI));
    365
    366			tty_flip_buffer_push(&port->state->port);
    367		}
    368	}
    369
    370	serial8250_modem_status(up);
    371	if (lsr & UART_LSR_THRE)
    372		serial8250_tx_chars(up);
    373
    374	uart_unlock_and_check_sysrq_irqrestore(port, flags);
    375
    376	return 1;
    377}
    378
    379static void aspeed_vuart_auto_configure_sirq_polarity(
    380	struct aspeed_vuart *vuart, struct device_node *syscon_np,
    381	u32 reg_offset, u32 reg_mask)
    382{
    383	struct regmap *regmap;
    384	u32 value;
    385
    386	regmap = syscon_node_to_regmap(syscon_np);
    387	if (IS_ERR(regmap)) {
    388		dev_warn(vuart->dev,
    389			 "could not get regmap for aspeed,sirq-polarity-sense\n");
    390		return;
    391	}
    392	if (regmap_read(regmap, reg_offset, &value)) {
    393		dev_warn(vuart->dev, "could not read hw strap table\n");
    394		return;
    395	}
    396
    397	aspeed_vuart_set_sirq_polarity(vuart, (value & reg_mask) == 0);
    398}
    399
    400static int aspeed_vuart_map_irq_polarity(u32 dt)
    401{
    402	switch (dt) {
    403	case IRQ_TYPE_LEVEL_LOW:
    404		return 0;
    405	case IRQ_TYPE_LEVEL_HIGH:
    406		return 1;
    407	default:
    408		return -EINVAL;
    409	}
    410}
    411
    412static int aspeed_vuart_probe(struct platform_device *pdev)
    413{
    414	struct of_phandle_args sirq_polarity_sense_args;
    415	struct uart_8250_port port;
    416	struct aspeed_vuart *vuart;
    417	struct device_node *np;
    418	struct resource *res;
    419	u32 clk, prop, sirq[2];
    420	int rc, sirq_polarity;
    421
    422	np = pdev->dev.of_node;
    423
    424	vuart = devm_kzalloc(&pdev->dev, sizeof(*vuart), GFP_KERNEL);
    425	if (!vuart)
    426		return -ENOMEM;
    427
    428	vuart->dev = &pdev->dev;
    429	timer_setup(&vuart->unthrottle_timer, aspeed_vuart_unthrottle_exp, 0);
    430
    431	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    432	if (!res)
    433		return -EINVAL;
    434
    435	memset(&port, 0, sizeof(port));
    436	port.port.private_data = vuart;
    437	port.port.mapbase = res->start;
    438	port.port.mapsize = resource_size(res);
    439	port.port.startup = aspeed_vuart_startup;
    440	port.port.shutdown = aspeed_vuart_shutdown;
    441	port.port.throttle = aspeed_vuart_throttle;
    442	port.port.unthrottle = aspeed_vuart_unthrottle;
    443	port.port.status = UPSTAT_SYNC_FIFO;
    444	port.port.dev = &pdev->dev;
    445	port.port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE);
    446	port.bugs |= UART_BUG_TXRACE;
    447
    448	rc = sysfs_create_group(&vuart->dev->kobj, &aspeed_vuart_attr_group);
    449	if (rc < 0)
    450		return rc;
    451
    452	if (of_property_read_u32(np, "clock-frequency", &clk)) {
    453		vuart->clk = devm_clk_get(&pdev->dev, NULL);
    454		if (IS_ERR(vuart->clk)) {
    455			dev_warn(&pdev->dev,
    456				"clk or clock-frequency not defined\n");
    457			rc = PTR_ERR(vuart->clk);
    458			goto err_sysfs_remove;
    459		}
    460
    461		rc = clk_prepare_enable(vuart->clk);
    462		if (rc < 0)
    463			goto err_sysfs_remove;
    464
    465		clk = clk_get_rate(vuart->clk);
    466	}
    467
    468	/* If current-speed was set, then try not to change it. */
    469	if (of_property_read_u32(np, "current-speed", &prop) == 0)
    470		port.port.custom_divisor = clk / (16 * prop);
    471
    472	/* Check for shifted address mapping */
    473	if (of_property_read_u32(np, "reg-offset", &prop) == 0)
    474		port.port.mapbase += prop;
    475
    476	/* Check for registers offset within the devices address range */
    477	if (of_property_read_u32(np, "reg-shift", &prop) == 0)
    478		port.port.regshift = prop;
    479
    480	/* Check for fifo size */
    481	if (of_property_read_u32(np, "fifo-size", &prop) == 0)
    482		port.port.fifosize = prop;
    483
    484	/* Check for a fixed line number */
    485	rc = of_alias_get_id(np, "serial");
    486	if (rc >= 0)
    487		port.port.line = rc;
    488
    489	port.port.irq = irq_of_parse_and_map(np, 0);
    490	port.port.handle_irq = aspeed_vuart_handle_irq;
    491	port.port.iotype = UPIO_MEM;
    492	port.port.type = PORT_ASPEED_VUART;
    493	port.port.uartclk = clk;
    494	port.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP
    495		| UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_NO_THRE_TEST;
    496
    497	if (of_property_read_bool(np, "no-loopback-test"))
    498		port.port.flags |= UPF_SKIP_TEST;
    499
    500	if (port.port.fifosize)
    501		port.capabilities = UART_CAP_FIFO;
    502
    503	if (of_property_read_bool(np, "auto-flow-control"))
    504		port.capabilities |= UART_CAP_AFE;
    505
    506	rc = serial8250_register_8250_port(&port);
    507	if (rc < 0)
    508		goto err_clk_disable;
    509
    510	vuart->line = rc;
    511	vuart->port = serial8250_get_port(vuart->line);
    512
    513	rc = of_parse_phandle_with_fixed_args(
    514		np, "aspeed,sirq-polarity-sense", 2, 0,
    515		&sirq_polarity_sense_args);
    516	if (rc < 0) {
    517		dev_dbg(&pdev->dev,
    518			"aspeed,sirq-polarity-sense property not found\n");
    519	} else {
    520		aspeed_vuart_auto_configure_sirq_polarity(
    521			vuart, sirq_polarity_sense_args.np,
    522			sirq_polarity_sense_args.args[0],
    523			BIT(sirq_polarity_sense_args.args[1]));
    524		of_node_put(sirq_polarity_sense_args.np);
    525	}
    526
    527	rc = of_property_read_u32(np, "aspeed,lpc-io-reg", &prop);
    528	if (rc < 0)
    529		prop = ASPEED_VUART_DEFAULT_LPC_ADDR;
    530
    531	rc = aspeed_vuart_set_lpc_address(vuart, prop);
    532	if (rc < 0) {
    533		dev_err(&pdev->dev, "invalid value in aspeed,lpc-io-reg property\n");
    534		goto err_clk_disable;
    535	}
    536
    537	rc = of_property_read_u32_array(np, "aspeed,lpc-interrupts", sirq, 2);
    538	if (rc < 0) {
    539		sirq[0] = ASPEED_VUART_DEFAULT_SIRQ;
    540		sirq[1] = ASPEED_VUART_DEFAULT_SIRQ_POLARITY;
    541	}
    542
    543	rc = aspeed_vuart_set_sirq(vuart, sirq[0]);
    544	if (rc < 0) {
    545		dev_err(&pdev->dev, "invalid sirq number in aspeed,lpc-interrupts property\n");
    546		goto err_clk_disable;
    547	}
    548
    549	sirq_polarity = aspeed_vuart_map_irq_polarity(sirq[1]);
    550	if (sirq_polarity < 0) {
    551		dev_err(&pdev->dev, "invalid sirq polarity in aspeed,lpc-interrupts property\n");
    552		rc = sirq_polarity;
    553		goto err_clk_disable;
    554	}
    555
    556	aspeed_vuart_set_sirq_polarity(vuart, sirq_polarity);
    557
    558	aspeed_vuart_set_enabled(vuart, true);
    559	aspeed_vuart_set_host_tx_discard(vuart, true);
    560	platform_set_drvdata(pdev, vuart);
    561
    562	return 0;
    563
    564err_clk_disable:
    565	clk_disable_unprepare(vuart->clk);
    566	irq_dispose_mapping(port.port.irq);
    567err_sysfs_remove:
    568	sysfs_remove_group(&vuart->dev->kobj, &aspeed_vuart_attr_group);
    569	return rc;
    570}
    571
    572static int aspeed_vuart_remove(struct platform_device *pdev)
    573{
    574	struct aspeed_vuart *vuart = platform_get_drvdata(pdev);
    575
    576	del_timer_sync(&vuart->unthrottle_timer);
    577	aspeed_vuart_set_enabled(vuart, false);
    578	serial8250_unregister_port(vuart->line);
    579	sysfs_remove_group(&vuart->dev->kobj, &aspeed_vuart_attr_group);
    580	clk_disable_unprepare(vuart->clk);
    581
    582	return 0;
    583}
    584
    585static const struct of_device_id aspeed_vuart_table[] = {
    586	{ .compatible = "aspeed,ast2400-vuart" },
    587	{ .compatible = "aspeed,ast2500-vuart" },
    588	{ },
    589};
    590
    591static struct platform_driver aspeed_vuart_driver = {
    592	.driver = {
    593		.name = "aspeed-vuart",
    594		.of_match_table = aspeed_vuart_table,
    595	},
    596	.probe = aspeed_vuart_probe,
    597	.remove = aspeed_vuart_remove,
    598};
    599
    600module_platform_driver(aspeed_vuart_driver);
    601
    602MODULE_AUTHOR("Jeremy Kerr <jk@ozlabs.org>");
    603MODULE_LICENSE("GPL");
    604MODULE_DESCRIPTION("Driver for Aspeed VUART device");