.. | .. |
---|
10 | 10 | #include <linux/of_address.h> |
---|
11 | 11 | #include <linux/of_irq.h> |
---|
12 | 12 | #include <linux/of_platform.h> |
---|
| 13 | +#include <linux/regmap.h> |
---|
| 14 | +#include <linux/mfd/syscon.h> |
---|
13 | 15 | #include <linux/tty.h> |
---|
14 | 16 | #include <linux/tty_flip.h> |
---|
15 | 17 | #include <linux/clk.h> |
---|
.. | .. |
---|
18 | 20 | |
---|
19 | 21 | #define ASPEED_VUART_GCRA 0x20 |
---|
20 | 22 | #define ASPEED_VUART_GCRA_VUART_EN BIT(0) |
---|
| 23 | +#define ASPEED_VUART_GCRA_HOST_SIRQ_POLARITY BIT(1) |
---|
21 | 24 | #define ASPEED_VUART_GCRA_DISABLE_HOST_TX_DISCARD BIT(5) |
---|
22 | 25 | #define ASPEED_VUART_GCRB 0x24 |
---|
23 | 26 | #define ASPEED_VUART_GCRB_HOST_SIRQ_MASK GENMASK(7, 4) |
---|
.. | .. |
---|
127 | 130 | |
---|
128 | 131 | static DEVICE_ATTR_RW(sirq); |
---|
129 | 132 | |
---|
| 133 | +static ssize_t sirq_polarity_show(struct device *dev, |
---|
| 134 | + struct device_attribute *attr, char *buf) |
---|
| 135 | +{ |
---|
| 136 | + struct aspeed_vuart *vuart = dev_get_drvdata(dev); |
---|
| 137 | + u8 reg; |
---|
| 138 | + |
---|
| 139 | + reg = readb(vuart->regs + ASPEED_VUART_GCRA); |
---|
| 140 | + reg &= ASPEED_VUART_GCRA_HOST_SIRQ_POLARITY; |
---|
| 141 | + |
---|
| 142 | + return snprintf(buf, PAGE_SIZE - 1, "%u\n", reg ? 1 : 0); |
---|
| 143 | +} |
---|
| 144 | + |
---|
| 145 | +static void aspeed_vuart_set_sirq_polarity(struct aspeed_vuart *vuart, |
---|
| 146 | + bool polarity) |
---|
| 147 | +{ |
---|
| 148 | + u8 reg = readb(vuart->regs + ASPEED_VUART_GCRA); |
---|
| 149 | + |
---|
| 150 | + if (polarity) |
---|
| 151 | + reg |= ASPEED_VUART_GCRA_HOST_SIRQ_POLARITY; |
---|
| 152 | + else |
---|
| 153 | + reg &= ~ASPEED_VUART_GCRA_HOST_SIRQ_POLARITY; |
---|
| 154 | + |
---|
| 155 | + writeb(reg, vuart->regs + ASPEED_VUART_GCRA); |
---|
| 156 | +} |
---|
| 157 | + |
---|
| 158 | +static ssize_t sirq_polarity_store(struct device *dev, |
---|
| 159 | + struct device_attribute *attr, |
---|
| 160 | + const char *buf, size_t count) |
---|
| 161 | +{ |
---|
| 162 | + struct aspeed_vuart *vuart = dev_get_drvdata(dev); |
---|
| 163 | + unsigned long val; |
---|
| 164 | + int err; |
---|
| 165 | + |
---|
| 166 | + err = kstrtoul(buf, 0, &val); |
---|
| 167 | + if (err) |
---|
| 168 | + return err; |
---|
| 169 | + |
---|
| 170 | + aspeed_vuart_set_sirq_polarity(vuart, val != 0); |
---|
| 171 | + |
---|
| 172 | + return count; |
---|
| 173 | +} |
---|
| 174 | + |
---|
| 175 | +static DEVICE_ATTR_RW(sirq_polarity); |
---|
| 176 | + |
---|
130 | 177 | static struct attribute *aspeed_vuart_attrs[] = { |
---|
131 | 178 | &dev_attr_sirq.attr, |
---|
| 179 | + &dev_attr_sirq_polarity.attr, |
---|
132 | 180 | &dev_attr_lpc_address.attr, |
---|
133 | 181 | NULL, |
---|
134 | 182 | }; |
---|
.. | .. |
---|
293 | 341 | if (lsr & UART_LSR_THRE) |
---|
294 | 342 | serial8250_tx_chars(up); |
---|
295 | 343 | |
---|
296 | | - spin_unlock_irqrestore(&port->lock, flags); |
---|
| 344 | + uart_unlock_and_check_sysrq(port, flags); |
---|
297 | 345 | |
---|
298 | 346 | return 1; |
---|
299 | 347 | } |
---|
300 | 348 | |
---|
| 349 | +static void aspeed_vuart_auto_configure_sirq_polarity( |
---|
| 350 | + struct aspeed_vuart *vuart, struct device_node *syscon_np, |
---|
| 351 | + u32 reg_offset, u32 reg_mask) |
---|
| 352 | +{ |
---|
| 353 | + struct regmap *regmap; |
---|
| 354 | + u32 value; |
---|
| 355 | + |
---|
| 356 | + regmap = syscon_node_to_regmap(syscon_np); |
---|
| 357 | + if (IS_ERR(regmap)) { |
---|
| 358 | + dev_warn(vuart->dev, |
---|
| 359 | + "could not get regmap for aspeed,sirq-polarity-sense\n"); |
---|
| 360 | + return; |
---|
| 361 | + } |
---|
| 362 | + if (regmap_read(regmap, reg_offset, &value)) { |
---|
| 363 | + dev_warn(vuart->dev, "could not read hw strap table\n"); |
---|
| 364 | + return; |
---|
| 365 | + } |
---|
| 366 | + |
---|
| 367 | + aspeed_vuart_set_sirq_polarity(vuart, (value & reg_mask) == 0); |
---|
| 368 | +} |
---|
| 369 | + |
---|
301 | 370 | static int aspeed_vuart_probe(struct platform_device *pdev) |
---|
302 | 371 | { |
---|
| 372 | + struct of_phandle_args sirq_polarity_sense_args; |
---|
303 | 373 | struct uart_8250_port port; |
---|
304 | 374 | struct aspeed_vuart *vuart; |
---|
305 | 375 | struct device_node *np; |
---|
.. | .. |
---|
332 | 402 | port.port.unthrottle = aspeed_vuart_unthrottle; |
---|
333 | 403 | port.port.status = UPSTAT_SYNC_FIFO; |
---|
334 | 404 | port.port.dev = &pdev->dev; |
---|
| 405 | + port.port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE); |
---|
| 406 | + port.bugs |= UART_BUG_TXRACE; |
---|
335 | 407 | |
---|
336 | 408 | rc = sysfs_create_group(&vuart->dev->kobj, &aspeed_vuart_attr_group); |
---|
337 | 409 | if (rc < 0) |
---|
.. | .. |
---|
397 | 469 | |
---|
398 | 470 | vuart->line = rc; |
---|
399 | 471 | |
---|
| 472 | + rc = of_parse_phandle_with_fixed_args( |
---|
| 473 | + np, "aspeed,sirq-polarity-sense", 2, 0, |
---|
| 474 | + &sirq_polarity_sense_args); |
---|
| 475 | + if (rc < 0) { |
---|
| 476 | + dev_dbg(&pdev->dev, |
---|
| 477 | + "aspeed,sirq-polarity-sense property not found\n"); |
---|
| 478 | + } else { |
---|
| 479 | + aspeed_vuart_auto_configure_sirq_polarity( |
---|
| 480 | + vuart, sirq_polarity_sense_args.np, |
---|
| 481 | + sirq_polarity_sense_args.args[0], |
---|
| 482 | + BIT(sirq_polarity_sense_args.args[1])); |
---|
| 483 | + of_node_put(sirq_polarity_sense_args.np); |
---|
| 484 | + } |
---|
| 485 | + |
---|
400 | 486 | aspeed_vuart_set_enabled(vuart, true); |
---|
401 | 487 | aspeed_vuart_set_host_tx_discard(vuart, true); |
---|
402 | 488 | platform_set_drvdata(pdev, vuart); |
---|