162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Synopsys DesignWare 8250 driver. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2011 Picochip, Jamie Iles. 662306a36Sopenharmony_ci * Copyright 2013 Intel Corporation 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * The Synopsys DesignWare 8250 has an extra feature whereby it detects if the 962306a36Sopenharmony_ci * LCR is written whilst busy. If it is, then a busy detect interrupt is 1062306a36Sopenharmony_ci * raised, the LCR needs to be rewritten and the uart status register read. 1162306a36Sopenharmony_ci */ 1262306a36Sopenharmony_ci#include <linux/acpi.h> 1362306a36Sopenharmony_ci#include <linux/clk.h> 1462306a36Sopenharmony_ci#include <linux/delay.h> 1562306a36Sopenharmony_ci#include <linux/device.h> 1662306a36Sopenharmony_ci#include <linux/io.h> 1762306a36Sopenharmony_ci#include <linux/mod_devicetable.h> 1862306a36Sopenharmony_ci#include <linux/module.h> 1962306a36Sopenharmony_ci#include <linux/notifier.h> 2062306a36Sopenharmony_ci#include <linux/of.h> 2162306a36Sopenharmony_ci#include <linux/platform_device.h> 2262306a36Sopenharmony_ci#include <linux/pm_runtime.h> 2362306a36Sopenharmony_ci#include <linux/property.h> 2462306a36Sopenharmony_ci#include <linux/reset.h> 2562306a36Sopenharmony_ci#include <linux/slab.h> 2662306a36Sopenharmony_ci#include <linux/workqueue.h> 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#include <asm/byteorder.h> 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#include <linux/serial_8250.h> 3162306a36Sopenharmony_ci#include <linux/serial_reg.h> 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#include "8250_dwlib.h" 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci/* Offsets for the DesignWare specific registers */ 3662306a36Sopenharmony_ci#define DW_UART_USR 0x1f /* UART Status Register */ 3762306a36Sopenharmony_ci#define DW_UART_DMASA 0xa8 /* DMA Software Ack */ 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci#define OCTEON_UART_USR 0x27 /* UART Status Register */ 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci#define RZN1_UART_TDMACR 0x10c /* DMA Control Register Transmit Mode */ 4262306a36Sopenharmony_ci#define RZN1_UART_RDMACR 0x110 /* DMA Control Register Receive Mode */ 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci/* DesignWare specific register fields */ 4562306a36Sopenharmony_ci#define DW_UART_MCR_SIRE BIT(6) 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci/* Renesas specific register fields */ 4862306a36Sopenharmony_ci#define RZN1_UART_xDMACR_DMA_EN BIT(0) 4962306a36Sopenharmony_ci#define RZN1_UART_xDMACR_1_WORD_BURST (0 << 1) 5062306a36Sopenharmony_ci#define RZN1_UART_xDMACR_4_WORD_BURST (1 << 1) 5162306a36Sopenharmony_ci#define RZN1_UART_xDMACR_8_WORD_BURST (2 << 1) 5262306a36Sopenharmony_ci#define RZN1_UART_xDMACR_BLK_SZ(x) ((x) << 3) 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci/* Quirks */ 5562306a36Sopenharmony_ci#define DW_UART_QUIRK_OCTEON BIT(0) 5662306a36Sopenharmony_ci#define DW_UART_QUIRK_ARMADA_38X BIT(1) 5762306a36Sopenharmony_ci#define DW_UART_QUIRK_SKIP_SET_RATE BIT(2) 5862306a36Sopenharmony_ci#define DW_UART_QUIRK_IS_DMA_FC BIT(3) 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_cistatic inline struct dw8250_data *clk_to_dw8250_data(struct notifier_block *nb) 6162306a36Sopenharmony_ci{ 6262306a36Sopenharmony_ci return container_of(nb, struct dw8250_data, clk_notifier); 6362306a36Sopenharmony_ci} 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cistatic inline struct dw8250_data *work_to_dw8250_data(struct work_struct *work) 6662306a36Sopenharmony_ci{ 6762306a36Sopenharmony_ci return container_of(work, struct dw8250_data, clk_work); 6862306a36Sopenharmony_ci} 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cistatic inline int dw8250_modify_msr(struct uart_port *p, int offset, int value) 7162306a36Sopenharmony_ci{ 7262306a36Sopenharmony_ci struct dw8250_data *d = to_dw8250_data(p->private_data); 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci /* Override any modem control signals if needed */ 7562306a36Sopenharmony_ci if (offset == UART_MSR) { 7662306a36Sopenharmony_ci value |= d->msr_mask_on; 7762306a36Sopenharmony_ci value &= ~d->msr_mask_off; 7862306a36Sopenharmony_ci } 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci return value; 8162306a36Sopenharmony_ci} 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_cistatic void dw8250_force_idle(struct uart_port *p) 8462306a36Sopenharmony_ci{ 8562306a36Sopenharmony_ci struct uart_8250_port *up = up_to_u8250p(p); 8662306a36Sopenharmony_ci unsigned int lsr; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci serial8250_clear_and_reinit_fifos(up); 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci /* 9162306a36Sopenharmony_ci * With PSLVERR_RESP_EN parameter set to 1, the device generates an 9262306a36Sopenharmony_ci * error response when an attempt to read an empty RBR with FIFO 9362306a36Sopenharmony_ci * enabled. 9462306a36Sopenharmony_ci */ 9562306a36Sopenharmony_ci if (up->fcr & UART_FCR_ENABLE_FIFO) { 9662306a36Sopenharmony_ci lsr = p->serial_in(p, UART_LSR); 9762306a36Sopenharmony_ci if (!(lsr & UART_LSR_DR)) 9862306a36Sopenharmony_ci return; 9962306a36Sopenharmony_ci } 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci (void)p->serial_in(p, UART_RX); 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_cistatic void dw8250_check_lcr(struct uart_port *p, int value) 10562306a36Sopenharmony_ci{ 10662306a36Sopenharmony_ci void __iomem *offset = p->membase + (UART_LCR << p->regshift); 10762306a36Sopenharmony_ci int tries = 1000; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci /* Make sure LCR write wasn't ignored */ 11062306a36Sopenharmony_ci while (tries--) { 11162306a36Sopenharmony_ci unsigned int lcr = p->serial_in(p, UART_LCR); 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR)) 11462306a36Sopenharmony_ci return; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci dw8250_force_idle(p); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci#ifdef CONFIG_64BIT 11962306a36Sopenharmony_ci if (p->type == PORT_OCTEON) 12062306a36Sopenharmony_ci __raw_writeq(value & 0xff, offset); 12162306a36Sopenharmony_ci else 12262306a36Sopenharmony_ci#endif 12362306a36Sopenharmony_ci if (p->iotype == UPIO_MEM32) 12462306a36Sopenharmony_ci writel(value, offset); 12562306a36Sopenharmony_ci else if (p->iotype == UPIO_MEM32BE) 12662306a36Sopenharmony_ci iowrite32be(value, offset); 12762306a36Sopenharmony_ci else 12862306a36Sopenharmony_ci writeb(value, offset); 12962306a36Sopenharmony_ci } 13062306a36Sopenharmony_ci /* 13162306a36Sopenharmony_ci * FIXME: this deadlocks if port->lock is already held 13262306a36Sopenharmony_ci * dev_err(p->dev, "Couldn't set LCR to %d\n", value); 13362306a36Sopenharmony_ci */ 13462306a36Sopenharmony_ci} 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci/* Returns once the transmitter is empty or we run out of retries */ 13762306a36Sopenharmony_cistatic void dw8250_tx_wait_empty(struct uart_port *p) 13862306a36Sopenharmony_ci{ 13962306a36Sopenharmony_ci struct uart_8250_port *up = up_to_u8250p(p); 14062306a36Sopenharmony_ci unsigned int tries = 20000; 14162306a36Sopenharmony_ci unsigned int delay_threshold = tries - 1000; 14262306a36Sopenharmony_ci unsigned int lsr; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci while (tries--) { 14562306a36Sopenharmony_ci lsr = readb (p->membase + (UART_LSR << p->regshift)); 14662306a36Sopenharmony_ci up->lsr_saved_flags |= lsr & up->lsr_save_mask; 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci if (lsr & UART_LSR_TEMT) 14962306a36Sopenharmony_ci break; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci /* The device is first given a chance to empty without delay, 15262306a36Sopenharmony_ci * to avoid slowdowns at high bitrates. If after 1000 tries 15362306a36Sopenharmony_ci * the buffer has still not emptied, allow more time for low- 15462306a36Sopenharmony_ci * speed links. */ 15562306a36Sopenharmony_ci if (tries < delay_threshold) 15662306a36Sopenharmony_ci udelay (1); 15762306a36Sopenharmony_ci } 15862306a36Sopenharmony_ci} 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_cistatic void dw8250_serial_out(struct uart_port *p, int offset, int value) 16162306a36Sopenharmony_ci{ 16262306a36Sopenharmony_ci struct dw8250_data *d = to_dw8250_data(p->private_data); 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci writeb(value, p->membase + (offset << p->regshift)); 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci if (offset == UART_LCR && !d->uart_16550_compatible) 16762306a36Sopenharmony_ci dw8250_check_lcr(p, value); 16862306a36Sopenharmony_ci} 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_cistatic void dw8250_serial_out38x(struct uart_port *p, int offset, int value) 17162306a36Sopenharmony_ci{ 17262306a36Sopenharmony_ci /* Allow the TX to drain before we reconfigure */ 17362306a36Sopenharmony_ci if (offset == UART_LCR) 17462306a36Sopenharmony_ci dw8250_tx_wait_empty(p); 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci dw8250_serial_out(p, offset, value); 17762306a36Sopenharmony_ci} 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_cistatic unsigned int dw8250_serial_in(struct uart_port *p, int offset) 18062306a36Sopenharmony_ci{ 18162306a36Sopenharmony_ci unsigned int value = readb(p->membase + (offset << p->regshift)); 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci return dw8250_modify_msr(p, offset, value); 18462306a36Sopenharmony_ci} 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci#ifdef CONFIG_64BIT 18762306a36Sopenharmony_cistatic unsigned int dw8250_serial_inq(struct uart_port *p, int offset) 18862306a36Sopenharmony_ci{ 18962306a36Sopenharmony_ci unsigned int value; 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci value = (u8)__raw_readq(p->membase + (offset << p->regshift)); 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci return dw8250_modify_msr(p, offset, value); 19462306a36Sopenharmony_ci} 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_cistatic void dw8250_serial_outq(struct uart_port *p, int offset, int value) 19762306a36Sopenharmony_ci{ 19862306a36Sopenharmony_ci struct dw8250_data *d = to_dw8250_data(p->private_data); 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci value &= 0xff; 20162306a36Sopenharmony_ci __raw_writeq(value, p->membase + (offset << p->regshift)); 20262306a36Sopenharmony_ci /* Read back to ensure register write ordering. */ 20362306a36Sopenharmony_ci __raw_readq(p->membase + (UART_LCR << p->regshift)); 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci if (offset == UART_LCR && !d->uart_16550_compatible) 20662306a36Sopenharmony_ci dw8250_check_lcr(p, value); 20762306a36Sopenharmony_ci} 20862306a36Sopenharmony_ci#endif /* CONFIG_64BIT */ 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_cistatic void dw8250_serial_out32(struct uart_port *p, int offset, int value) 21162306a36Sopenharmony_ci{ 21262306a36Sopenharmony_ci struct dw8250_data *d = to_dw8250_data(p->private_data); 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci writel(value, p->membase + (offset << p->regshift)); 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci if (offset == UART_LCR && !d->uart_16550_compatible) 21762306a36Sopenharmony_ci dw8250_check_lcr(p, value); 21862306a36Sopenharmony_ci} 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_cistatic unsigned int dw8250_serial_in32(struct uart_port *p, int offset) 22162306a36Sopenharmony_ci{ 22262306a36Sopenharmony_ci unsigned int value = readl(p->membase + (offset << p->regshift)); 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci return dw8250_modify_msr(p, offset, value); 22562306a36Sopenharmony_ci} 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_cistatic void dw8250_serial_out32be(struct uart_port *p, int offset, int value) 22862306a36Sopenharmony_ci{ 22962306a36Sopenharmony_ci struct dw8250_data *d = to_dw8250_data(p->private_data); 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci iowrite32be(value, p->membase + (offset << p->regshift)); 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci if (offset == UART_LCR && !d->uart_16550_compatible) 23462306a36Sopenharmony_ci dw8250_check_lcr(p, value); 23562306a36Sopenharmony_ci} 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_cistatic unsigned int dw8250_serial_in32be(struct uart_port *p, int offset) 23862306a36Sopenharmony_ci{ 23962306a36Sopenharmony_ci unsigned int value = ioread32be(p->membase + (offset << p->regshift)); 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci return dw8250_modify_msr(p, offset, value); 24262306a36Sopenharmony_ci} 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_cistatic int dw8250_handle_irq(struct uart_port *p) 24662306a36Sopenharmony_ci{ 24762306a36Sopenharmony_ci struct uart_8250_port *up = up_to_u8250p(p); 24862306a36Sopenharmony_ci struct dw8250_data *d = to_dw8250_data(p->private_data); 24962306a36Sopenharmony_ci unsigned int iir = p->serial_in(p, UART_IIR); 25062306a36Sopenharmony_ci bool rx_timeout = (iir & 0x3f) == UART_IIR_RX_TIMEOUT; 25162306a36Sopenharmony_ci unsigned int quirks = d->pdata->quirks; 25262306a36Sopenharmony_ci unsigned int status; 25362306a36Sopenharmony_ci unsigned long flags; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci /* 25662306a36Sopenharmony_ci * There are ways to get Designware-based UARTs into a state where 25762306a36Sopenharmony_ci * they are asserting UART_IIR_RX_TIMEOUT but there is no actual 25862306a36Sopenharmony_ci * data available. If we see such a case then we'll do a bogus 25962306a36Sopenharmony_ci * read. If we don't do this then the "RX TIMEOUT" interrupt will 26062306a36Sopenharmony_ci * fire forever. 26162306a36Sopenharmony_ci * 26262306a36Sopenharmony_ci * This problem has only been observed so far when not in DMA mode 26362306a36Sopenharmony_ci * so we limit the workaround only to non-DMA mode. 26462306a36Sopenharmony_ci */ 26562306a36Sopenharmony_ci if (!up->dma && rx_timeout) { 26662306a36Sopenharmony_ci spin_lock_irqsave(&p->lock, flags); 26762306a36Sopenharmony_ci status = serial_lsr_in(up); 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci if (!(status & (UART_LSR_DR | UART_LSR_BI))) 27062306a36Sopenharmony_ci (void) p->serial_in(p, UART_RX); 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci spin_unlock_irqrestore(&p->lock, flags); 27362306a36Sopenharmony_ci } 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci /* Manually stop the Rx DMA transfer when acting as flow controller */ 27662306a36Sopenharmony_ci if (quirks & DW_UART_QUIRK_IS_DMA_FC && up->dma && up->dma->rx_running && rx_timeout) { 27762306a36Sopenharmony_ci spin_lock_irqsave(&p->lock, flags); 27862306a36Sopenharmony_ci status = serial_lsr_in(up); 27962306a36Sopenharmony_ci spin_unlock_irqrestore(&p->lock, flags); 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci if (status & (UART_LSR_DR | UART_LSR_BI)) { 28262306a36Sopenharmony_ci dw8250_writel_ext(p, RZN1_UART_RDMACR, 0); 28362306a36Sopenharmony_ci dw8250_writel_ext(p, DW_UART_DMASA, 1); 28462306a36Sopenharmony_ci } 28562306a36Sopenharmony_ci } 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci if (serial8250_handle_irq(p, iir)) 28862306a36Sopenharmony_ci return 1; 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) { 29162306a36Sopenharmony_ci /* Clear the USR */ 29262306a36Sopenharmony_ci (void)p->serial_in(p, d->pdata->usr_reg); 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci return 1; 29562306a36Sopenharmony_ci } 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci return 0; 29862306a36Sopenharmony_ci} 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_cistatic void dw8250_clk_work_cb(struct work_struct *work) 30162306a36Sopenharmony_ci{ 30262306a36Sopenharmony_ci struct dw8250_data *d = work_to_dw8250_data(work); 30362306a36Sopenharmony_ci struct uart_8250_port *up; 30462306a36Sopenharmony_ci unsigned long rate; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci rate = clk_get_rate(d->clk); 30762306a36Sopenharmony_ci if (rate <= 0) 30862306a36Sopenharmony_ci return; 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci up = serial8250_get_port(d->data.line); 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci serial8250_update_uartclk(&up->port, rate); 31362306a36Sopenharmony_ci} 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_cistatic int dw8250_clk_notifier_cb(struct notifier_block *nb, 31662306a36Sopenharmony_ci unsigned long event, void *data) 31762306a36Sopenharmony_ci{ 31862306a36Sopenharmony_ci struct dw8250_data *d = clk_to_dw8250_data(nb); 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci /* 32162306a36Sopenharmony_ci * We have no choice but to defer the uartclk update due to two 32262306a36Sopenharmony_ci * deadlocks. First one is caused by a recursive mutex lock which 32362306a36Sopenharmony_ci * happens when clk_set_rate() is called from dw8250_set_termios(). 32462306a36Sopenharmony_ci * Second deadlock is more tricky and is caused by an inverted order of 32562306a36Sopenharmony_ci * the clk and tty-port mutexes lock. It happens if clock rate change 32662306a36Sopenharmony_ci * is requested asynchronously while set_termios() is executed between 32762306a36Sopenharmony_ci * tty-port mutex lock and clk_set_rate() function invocation and 32862306a36Sopenharmony_ci * vise-versa. Anyway if we didn't have the reference clock alteration 32962306a36Sopenharmony_ci * in the dw8250_set_termios() method we wouldn't have needed this 33062306a36Sopenharmony_ci * deferred event handling complication. 33162306a36Sopenharmony_ci */ 33262306a36Sopenharmony_ci if (event == POST_RATE_CHANGE) { 33362306a36Sopenharmony_ci queue_work(system_unbound_wq, &d->clk_work); 33462306a36Sopenharmony_ci return NOTIFY_OK; 33562306a36Sopenharmony_ci } 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci return NOTIFY_DONE; 33862306a36Sopenharmony_ci} 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_cistatic void 34162306a36Sopenharmony_cidw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old) 34262306a36Sopenharmony_ci{ 34362306a36Sopenharmony_ci if (!state) 34462306a36Sopenharmony_ci pm_runtime_get_sync(port->dev); 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci serial8250_do_pm(port, state, old); 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci if (state) 34962306a36Sopenharmony_ci pm_runtime_put_sync_suspend(port->dev); 35062306a36Sopenharmony_ci} 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_cistatic void dw8250_set_termios(struct uart_port *p, struct ktermios *termios, 35362306a36Sopenharmony_ci const struct ktermios *old) 35462306a36Sopenharmony_ci{ 35562306a36Sopenharmony_ci unsigned long newrate = tty_termios_baud_rate(termios) * 16; 35662306a36Sopenharmony_ci struct dw8250_data *d = to_dw8250_data(p->private_data); 35762306a36Sopenharmony_ci long rate; 35862306a36Sopenharmony_ci int ret; 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci clk_disable_unprepare(d->clk); 36162306a36Sopenharmony_ci rate = clk_round_rate(d->clk, newrate); 36262306a36Sopenharmony_ci if (rate > 0) { 36362306a36Sopenharmony_ci /* 36462306a36Sopenharmony_ci * Note that any clock-notifer worker will block in 36562306a36Sopenharmony_ci * serial8250_update_uartclk() until we are done. 36662306a36Sopenharmony_ci */ 36762306a36Sopenharmony_ci ret = clk_set_rate(d->clk, newrate); 36862306a36Sopenharmony_ci if (!ret) 36962306a36Sopenharmony_ci p->uartclk = rate; 37062306a36Sopenharmony_ci } 37162306a36Sopenharmony_ci clk_prepare_enable(d->clk); 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci dw8250_do_set_termios(p, termios, old); 37462306a36Sopenharmony_ci} 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_cistatic void dw8250_set_ldisc(struct uart_port *p, struct ktermios *termios) 37762306a36Sopenharmony_ci{ 37862306a36Sopenharmony_ci struct uart_8250_port *up = up_to_u8250p(p); 37962306a36Sopenharmony_ci unsigned int mcr = p->serial_in(p, UART_MCR); 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci if (up->capabilities & UART_CAP_IRDA) { 38262306a36Sopenharmony_ci if (termios->c_line == N_IRDA) 38362306a36Sopenharmony_ci mcr |= DW_UART_MCR_SIRE; 38462306a36Sopenharmony_ci else 38562306a36Sopenharmony_ci mcr &= ~DW_UART_MCR_SIRE; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci p->serial_out(p, UART_MCR, mcr); 38862306a36Sopenharmony_ci } 38962306a36Sopenharmony_ci serial8250_do_set_ldisc(p, termios); 39062306a36Sopenharmony_ci} 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci/* 39362306a36Sopenharmony_ci * dw8250_fallback_dma_filter will prevent the UART from getting just any free 39462306a36Sopenharmony_ci * channel on platforms that have DMA engines, but don't have any channels 39562306a36Sopenharmony_ci * assigned to the UART. 39662306a36Sopenharmony_ci * 39762306a36Sopenharmony_ci * REVISIT: This is a work around for limitation in the DMA Engine API. Once the 39862306a36Sopenharmony_ci * core problem is fixed, this function is no longer needed. 39962306a36Sopenharmony_ci */ 40062306a36Sopenharmony_cistatic bool dw8250_fallback_dma_filter(struct dma_chan *chan, void *param) 40162306a36Sopenharmony_ci{ 40262306a36Sopenharmony_ci return false; 40362306a36Sopenharmony_ci} 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_cistatic bool dw8250_idma_filter(struct dma_chan *chan, void *param) 40662306a36Sopenharmony_ci{ 40762306a36Sopenharmony_ci return param == chan->device->dev; 40862306a36Sopenharmony_ci} 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_cistatic u32 dw8250_rzn1_get_dmacr_burst(int max_burst) 41162306a36Sopenharmony_ci{ 41262306a36Sopenharmony_ci if (max_burst >= 8) 41362306a36Sopenharmony_ci return RZN1_UART_xDMACR_8_WORD_BURST; 41462306a36Sopenharmony_ci else if (max_burst >= 4) 41562306a36Sopenharmony_ci return RZN1_UART_xDMACR_4_WORD_BURST; 41662306a36Sopenharmony_ci else 41762306a36Sopenharmony_ci return RZN1_UART_xDMACR_1_WORD_BURST; 41862306a36Sopenharmony_ci} 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_cistatic void dw8250_prepare_tx_dma(struct uart_8250_port *p) 42162306a36Sopenharmony_ci{ 42262306a36Sopenharmony_ci struct uart_port *up = &p->port; 42362306a36Sopenharmony_ci struct uart_8250_dma *dma = p->dma; 42462306a36Sopenharmony_ci u32 val; 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci dw8250_writel_ext(up, RZN1_UART_TDMACR, 0); 42762306a36Sopenharmony_ci val = dw8250_rzn1_get_dmacr_burst(dma->txconf.dst_maxburst) | 42862306a36Sopenharmony_ci RZN1_UART_xDMACR_BLK_SZ(dma->tx_size) | 42962306a36Sopenharmony_ci RZN1_UART_xDMACR_DMA_EN; 43062306a36Sopenharmony_ci dw8250_writel_ext(up, RZN1_UART_TDMACR, val); 43162306a36Sopenharmony_ci} 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_cistatic void dw8250_prepare_rx_dma(struct uart_8250_port *p) 43462306a36Sopenharmony_ci{ 43562306a36Sopenharmony_ci struct uart_port *up = &p->port; 43662306a36Sopenharmony_ci struct uart_8250_dma *dma = p->dma; 43762306a36Sopenharmony_ci u32 val; 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci dw8250_writel_ext(up, RZN1_UART_RDMACR, 0); 44062306a36Sopenharmony_ci val = dw8250_rzn1_get_dmacr_burst(dma->rxconf.src_maxburst) | 44162306a36Sopenharmony_ci RZN1_UART_xDMACR_BLK_SZ(dma->rx_size) | 44262306a36Sopenharmony_ci RZN1_UART_xDMACR_DMA_EN; 44362306a36Sopenharmony_ci dw8250_writel_ext(up, RZN1_UART_RDMACR, val); 44462306a36Sopenharmony_ci} 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_cistatic void dw8250_quirks(struct uart_port *p, struct dw8250_data *data) 44762306a36Sopenharmony_ci{ 44862306a36Sopenharmony_ci struct device_node *np = p->dev->of_node; 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci if (np) { 45162306a36Sopenharmony_ci unsigned int quirks = data->pdata->quirks; 45262306a36Sopenharmony_ci int id; 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci /* get index of serial line, if found in DT aliases */ 45562306a36Sopenharmony_ci id = of_alias_get_id(np, "serial"); 45662306a36Sopenharmony_ci if (id >= 0) 45762306a36Sopenharmony_ci p->line = id; 45862306a36Sopenharmony_ci#ifdef CONFIG_64BIT 45962306a36Sopenharmony_ci if (quirks & DW_UART_QUIRK_OCTEON) { 46062306a36Sopenharmony_ci p->serial_in = dw8250_serial_inq; 46162306a36Sopenharmony_ci p->serial_out = dw8250_serial_outq; 46262306a36Sopenharmony_ci p->flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE; 46362306a36Sopenharmony_ci p->type = PORT_OCTEON; 46462306a36Sopenharmony_ci data->skip_autocfg = true; 46562306a36Sopenharmony_ci } 46662306a36Sopenharmony_ci#endif 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci if (of_device_is_big_endian(np)) { 46962306a36Sopenharmony_ci p->iotype = UPIO_MEM32BE; 47062306a36Sopenharmony_ci p->serial_in = dw8250_serial_in32be; 47162306a36Sopenharmony_ci p->serial_out = dw8250_serial_out32be; 47262306a36Sopenharmony_ci } 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci if (quirks & DW_UART_QUIRK_ARMADA_38X) 47562306a36Sopenharmony_ci p->serial_out = dw8250_serial_out38x; 47662306a36Sopenharmony_ci if (quirks & DW_UART_QUIRK_SKIP_SET_RATE) 47762306a36Sopenharmony_ci p->set_termios = dw8250_do_set_termios; 47862306a36Sopenharmony_ci if (quirks & DW_UART_QUIRK_IS_DMA_FC) { 47962306a36Sopenharmony_ci data->data.dma.txconf.device_fc = 1; 48062306a36Sopenharmony_ci data->data.dma.rxconf.device_fc = 1; 48162306a36Sopenharmony_ci data->data.dma.prepare_tx_dma = dw8250_prepare_tx_dma; 48262306a36Sopenharmony_ci data->data.dma.prepare_rx_dma = dw8250_prepare_rx_dma; 48362306a36Sopenharmony_ci } 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci } else if (acpi_dev_present("APMC0D08", NULL, -1)) { 48662306a36Sopenharmony_ci p->iotype = UPIO_MEM32; 48762306a36Sopenharmony_ci p->regshift = 2; 48862306a36Sopenharmony_ci p->serial_in = dw8250_serial_in32; 48962306a36Sopenharmony_ci data->uart_16550_compatible = true; 49062306a36Sopenharmony_ci } 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci /* Platforms with iDMA 64-bit */ 49362306a36Sopenharmony_ci if (platform_get_resource_byname(to_platform_device(p->dev), 49462306a36Sopenharmony_ci IORESOURCE_MEM, "lpss_priv")) { 49562306a36Sopenharmony_ci data->data.dma.rx_param = p->dev->parent; 49662306a36Sopenharmony_ci data->data.dma.tx_param = p->dev->parent; 49762306a36Sopenharmony_ci data->data.dma.fn = dw8250_idma_filter; 49862306a36Sopenharmony_ci } 49962306a36Sopenharmony_ci} 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_cistatic void dw8250_clk_disable_unprepare(void *data) 50262306a36Sopenharmony_ci{ 50362306a36Sopenharmony_ci clk_disable_unprepare(data); 50462306a36Sopenharmony_ci} 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_cistatic void dw8250_reset_control_assert(void *data) 50762306a36Sopenharmony_ci{ 50862306a36Sopenharmony_ci reset_control_assert(data); 50962306a36Sopenharmony_ci} 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_cistatic int dw8250_probe(struct platform_device *pdev) 51262306a36Sopenharmony_ci{ 51362306a36Sopenharmony_ci struct uart_8250_port uart = {}, *up = &uart; 51462306a36Sopenharmony_ci struct uart_port *p = &up->port; 51562306a36Sopenharmony_ci struct device *dev = &pdev->dev; 51662306a36Sopenharmony_ci struct dw8250_data *data; 51762306a36Sopenharmony_ci struct resource *regs; 51862306a36Sopenharmony_ci int irq; 51962306a36Sopenharmony_ci int err; 52062306a36Sopenharmony_ci u32 val; 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 52362306a36Sopenharmony_ci if (!regs) 52462306a36Sopenharmony_ci return dev_err_probe(dev, -EINVAL, "no registers defined\n"); 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci irq = platform_get_irq_optional(pdev, 0); 52762306a36Sopenharmony_ci /* no interrupt -> fall back to polling */ 52862306a36Sopenharmony_ci if (irq == -ENXIO) 52962306a36Sopenharmony_ci irq = 0; 53062306a36Sopenharmony_ci if (irq < 0) 53162306a36Sopenharmony_ci return irq; 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci spin_lock_init(&p->lock); 53462306a36Sopenharmony_ci p->mapbase = regs->start; 53562306a36Sopenharmony_ci p->irq = irq; 53662306a36Sopenharmony_ci p->handle_irq = dw8250_handle_irq; 53762306a36Sopenharmony_ci p->pm = dw8250_do_pm; 53862306a36Sopenharmony_ci p->type = PORT_8250; 53962306a36Sopenharmony_ci p->flags = UPF_SHARE_IRQ | UPF_FIXED_PORT; 54062306a36Sopenharmony_ci p->dev = dev; 54162306a36Sopenharmony_ci p->iotype = UPIO_MEM; 54262306a36Sopenharmony_ci p->serial_in = dw8250_serial_in; 54362306a36Sopenharmony_ci p->serial_out = dw8250_serial_out; 54462306a36Sopenharmony_ci p->set_ldisc = dw8250_set_ldisc; 54562306a36Sopenharmony_ci p->set_termios = dw8250_set_termios; 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci p->membase = devm_ioremap(dev, regs->start, resource_size(regs)); 54862306a36Sopenharmony_ci if (!p->membase) 54962306a36Sopenharmony_ci return -ENOMEM; 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 55262306a36Sopenharmony_ci if (!data) 55362306a36Sopenharmony_ci return -ENOMEM; 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci data->data.dma.fn = dw8250_fallback_dma_filter; 55662306a36Sopenharmony_ci data->pdata = device_get_match_data(p->dev); 55762306a36Sopenharmony_ci p->private_data = &data->data; 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci data->uart_16550_compatible = device_property_read_bool(dev, 56062306a36Sopenharmony_ci "snps,uart-16550-compatible"); 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci err = device_property_read_u32(dev, "reg-shift", &val); 56362306a36Sopenharmony_ci if (!err) 56462306a36Sopenharmony_ci p->regshift = val; 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci err = device_property_read_u32(dev, "reg-io-width", &val); 56762306a36Sopenharmony_ci if (!err && val == 4) { 56862306a36Sopenharmony_ci p->iotype = UPIO_MEM32; 56962306a36Sopenharmony_ci p->serial_in = dw8250_serial_in32; 57062306a36Sopenharmony_ci p->serial_out = dw8250_serial_out32; 57162306a36Sopenharmony_ci } 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci if (device_property_read_bool(dev, "dcd-override")) { 57462306a36Sopenharmony_ci /* Always report DCD as active */ 57562306a36Sopenharmony_ci data->msr_mask_on |= UART_MSR_DCD; 57662306a36Sopenharmony_ci data->msr_mask_off |= UART_MSR_DDCD; 57762306a36Sopenharmony_ci } 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci if (device_property_read_bool(dev, "dsr-override")) { 58062306a36Sopenharmony_ci /* Always report DSR as active */ 58162306a36Sopenharmony_ci data->msr_mask_on |= UART_MSR_DSR; 58262306a36Sopenharmony_ci data->msr_mask_off |= UART_MSR_DDSR; 58362306a36Sopenharmony_ci } 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci if (device_property_read_bool(dev, "cts-override")) { 58662306a36Sopenharmony_ci /* Always report CTS as active */ 58762306a36Sopenharmony_ci data->msr_mask_on |= UART_MSR_CTS; 58862306a36Sopenharmony_ci data->msr_mask_off |= UART_MSR_DCTS; 58962306a36Sopenharmony_ci } 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci if (device_property_read_bool(dev, "ri-override")) { 59262306a36Sopenharmony_ci /* Always report Ring indicator as inactive */ 59362306a36Sopenharmony_ci data->msr_mask_off |= UART_MSR_RI; 59462306a36Sopenharmony_ci data->msr_mask_off |= UART_MSR_TERI; 59562306a36Sopenharmony_ci } 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci /* Always ask for fixed clock rate from a property. */ 59862306a36Sopenharmony_ci device_property_read_u32(dev, "clock-frequency", &p->uartclk); 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci /* If there is separate baudclk, get the rate from it. */ 60162306a36Sopenharmony_ci data->clk = devm_clk_get_optional(dev, "baudclk"); 60262306a36Sopenharmony_ci if (data->clk == NULL) 60362306a36Sopenharmony_ci data->clk = devm_clk_get_optional(dev, NULL); 60462306a36Sopenharmony_ci if (IS_ERR(data->clk)) 60562306a36Sopenharmony_ci return PTR_ERR(data->clk); 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci INIT_WORK(&data->clk_work, dw8250_clk_work_cb); 60862306a36Sopenharmony_ci data->clk_notifier.notifier_call = dw8250_clk_notifier_cb; 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci err = clk_prepare_enable(data->clk); 61162306a36Sopenharmony_ci if (err) 61262306a36Sopenharmony_ci return dev_err_probe(dev, err, "could not enable optional baudclk\n"); 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci err = devm_add_action_or_reset(dev, dw8250_clk_disable_unprepare, data->clk); 61562306a36Sopenharmony_ci if (err) 61662306a36Sopenharmony_ci return err; 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci if (data->clk) 61962306a36Sopenharmony_ci p->uartclk = clk_get_rate(data->clk); 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci /* If no clock rate is defined, fail. */ 62262306a36Sopenharmony_ci if (!p->uartclk) 62362306a36Sopenharmony_ci return dev_err_probe(dev, -EINVAL, "clock rate not defined\n"); 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci data->pclk = devm_clk_get_optional(dev, "apb_pclk"); 62662306a36Sopenharmony_ci if (IS_ERR(data->pclk)) 62762306a36Sopenharmony_ci return PTR_ERR(data->pclk); 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci err = clk_prepare_enable(data->pclk); 63062306a36Sopenharmony_ci if (err) 63162306a36Sopenharmony_ci return dev_err_probe(dev, err, "could not enable apb_pclk\n"); 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci err = devm_add_action_or_reset(dev, dw8250_clk_disable_unprepare, data->pclk); 63462306a36Sopenharmony_ci if (err) 63562306a36Sopenharmony_ci return err; 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci data->rst = devm_reset_control_get_optional_exclusive(dev, NULL); 63862306a36Sopenharmony_ci if (IS_ERR(data->rst)) 63962306a36Sopenharmony_ci return PTR_ERR(data->rst); 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci reset_control_deassert(data->rst); 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci err = devm_add_action_or_reset(dev, dw8250_reset_control_assert, data->rst); 64462306a36Sopenharmony_ci if (err) 64562306a36Sopenharmony_ci return err; 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci dw8250_quirks(p, data); 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_ci /* If the Busy Functionality is not implemented, don't handle it */ 65062306a36Sopenharmony_ci if (data->uart_16550_compatible) 65162306a36Sopenharmony_ci p->handle_irq = NULL; 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_ci if (!data->skip_autocfg) 65462306a36Sopenharmony_ci dw8250_setup_port(p); 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci /* If we have a valid fifosize, try hooking up DMA */ 65762306a36Sopenharmony_ci if (p->fifosize) { 65862306a36Sopenharmony_ci data->data.dma.rxconf.src_maxburst = p->fifosize / 4; 65962306a36Sopenharmony_ci data->data.dma.txconf.dst_maxburst = p->fifosize / 4; 66062306a36Sopenharmony_ci up->dma = &data->data.dma; 66162306a36Sopenharmony_ci } 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci data->data.line = serial8250_register_8250_port(up); 66462306a36Sopenharmony_ci if (data->data.line < 0) 66562306a36Sopenharmony_ci return data->data.line; 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci /* 66862306a36Sopenharmony_ci * Some platforms may provide a reference clock shared between several 66962306a36Sopenharmony_ci * devices. In this case any clock state change must be known to the 67062306a36Sopenharmony_ci * UART port at least post factum. 67162306a36Sopenharmony_ci */ 67262306a36Sopenharmony_ci if (data->clk) { 67362306a36Sopenharmony_ci err = clk_notifier_register(data->clk, &data->clk_notifier); 67462306a36Sopenharmony_ci if (err) 67562306a36Sopenharmony_ci return dev_err_probe(dev, err, "Failed to set the clock notifier\n"); 67662306a36Sopenharmony_ci queue_work(system_unbound_wq, &data->clk_work); 67762306a36Sopenharmony_ci } 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci platform_set_drvdata(pdev, data); 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci pm_runtime_set_active(dev); 68262306a36Sopenharmony_ci pm_runtime_enable(dev); 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ci return 0; 68562306a36Sopenharmony_ci} 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_cistatic int dw8250_remove(struct platform_device *pdev) 68862306a36Sopenharmony_ci{ 68962306a36Sopenharmony_ci struct dw8250_data *data = platform_get_drvdata(pdev); 69062306a36Sopenharmony_ci struct device *dev = &pdev->dev; 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci pm_runtime_get_sync(dev); 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_ci if (data->clk) { 69562306a36Sopenharmony_ci clk_notifier_unregister(data->clk, &data->clk_notifier); 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci flush_work(&data->clk_work); 69862306a36Sopenharmony_ci } 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci serial8250_unregister_port(data->data.line); 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci pm_runtime_disable(dev); 70362306a36Sopenharmony_ci pm_runtime_put_noidle(dev); 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci return 0; 70662306a36Sopenharmony_ci} 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_cistatic int dw8250_suspend(struct device *dev) 70962306a36Sopenharmony_ci{ 71062306a36Sopenharmony_ci struct dw8250_data *data = dev_get_drvdata(dev); 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ci serial8250_suspend_port(data->data.line); 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci return 0; 71562306a36Sopenharmony_ci} 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_cistatic int dw8250_resume(struct device *dev) 71862306a36Sopenharmony_ci{ 71962306a36Sopenharmony_ci struct dw8250_data *data = dev_get_drvdata(dev); 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci serial8250_resume_port(data->data.line); 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci return 0; 72462306a36Sopenharmony_ci} 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_cistatic int dw8250_runtime_suspend(struct device *dev) 72762306a36Sopenharmony_ci{ 72862306a36Sopenharmony_ci struct dw8250_data *data = dev_get_drvdata(dev); 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci clk_disable_unprepare(data->clk); 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci clk_disable_unprepare(data->pclk); 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ci return 0; 73562306a36Sopenharmony_ci} 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_cistatic int dw8250_runtime_resume(struct device *dev) 73862306a36Sopenharmony_ci{ 73962306a36Sopenharmony_ci struct dw8250_data *data = dev_get_drvdata(dev); 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_ci clk_prepare_enable(data->pclk); 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci clk_prepare_enable(data->clk); 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci return 0; 74662306a36Sopenharmony_ci} 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_cistatic const struct dev_pm_ops dw8250_pm_ops = { 74962306a36Sopenharmony_ci SYSTEM_SLEEP_PM_OPS(dw8250_suspend, dw8250_resume) 75062306a36Sopenharmony_ci RUNTIME_PM_OPS(dw8250_runtime_suspend, dw8250_runtime_resume, NULL) 75162306a36Sopenharmony_ci}; 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_cistatic const struct dw8250_platform_data dw8250_dw_apb = { 75462306a36Sopenharmony_ci .usr_reg = DW_UART_USR, 75562306a36Sopenharmony_ci}; 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_cistatic const struct dw8250_platform_data dw8250_octeon_3860_data = { 75862306a36Sopenharmony_ci .usr_reg = OCTEON_UART_USR, 75962306a36Sopenharmony_ci .quirks = DW_UART_QUIRK_OCTEON, 76062306a36Sopenharmony_ci}; 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_cistatic const struct dw8250_platform_data dw8250_armada_38x_data = { 76362306a36Sopenharmony_ci .usr_reg = DW_UART_USR, 76462306a36Sopenharmony_ci .quirks = DW_UART_QUIRK_ARMADA_38X, 76562306a36Sopenharmony_ci}; 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_cistatic const struct dw8250_platform_data dw8250_renesas_rzn1_data = { 76862306a36Sopenharmony_ci .usr_reg = DW_UART_USR, 76962306a36Sopenharmony_ci .cpr_val = 0x00012f32, 77062306a36Sopenharmony_ci .quirks = DW_UART_QUIRK_IS_DMA_FC, 77162306a36Sopenharmony_ci}; 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_cistatic const struct dw8250_platform_data dw8250_starfive_jh7100_data = { 77462306a36Sopenharmony_ci .usr_reg = DW_UART_USR, 77562306a36Sopenharmony_ci .quirks = DW_UART_QUIRK_SKIP_SET_RATE, 77662306a36Sopenharmony_ci}; 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_cistatic const struct of_device_id dw8250_of_match[] = { 77962306a36Sopenharmony_ci { .compatible = "snps,dw-apb-uart", .data = &dw8250_dw_apb }, 78062306a36Sopenharmony_ci { .compatible = "cavium,octeon-3860-uart", .data = &dw8250_octeon_3860_data }, 78162306a36Sopenharmony_ci { .compatible = "marvell,armada-38x-uart", .data = &dw8250_armada_38x_data }, 78262306a36Sopenharmony_ci { .compatible = "renesas,rzn1-uart", .data = &dw8250_renesas_rzn1_data }, 78362306a36Sopenharmony_ci { .compatible = "starfive,jh7100-uart", .data = &dw8250_starfive_jh7100_data }, 78462306a36Sopenharmony_ci { /* Sentinel */ } 78562306a36Sopenharmony_ci}; 78662306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, dw8250_of_match); 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_cistatic const struct acpi_device_id dw8250_acpi_match[] = { 78962306a36Sopenharmony_ci { "80860F0A", (kernel_ulong_t)&dw8250_dw_apb }, 79062306a36Sopenharmony_ci { "8086228A", (kernel_ulong_t)&dw8250_dw_apb }, 79162306a36Sopenharmony_ci { "AMD0020", (kernel_ulong_t)&dw8250_dw_apb }, 79262306a36Sopenharmony_ci { "AMDI0020", (kernel_ulong_t)&dw8250_dw_apb }, 79362306a36Sopenharmony_ci { "AMDI0022", (kernel_ulong_t)&dw8250_dw_apb }, 79462306a36Sopenharmony_ci { "APMC0D08", (kernel_ulong_t)&dw8250_dw_apb}, 79562306a36Sopenharmony_ci { "BRCM2032", (kernel_ulong_t)&dw8250_dw_apb }, 79662306a36Sopenharmony_ci { "HISI0031", (kernel_ulong_t)&dw8250_dw_apb }, 79762306a36Sopenharmony_ci { "INT33C4", (kernel_ulong_t)&dw8250_dw_apb }, 79862306a36Sopenharmony_ci { "INT33C5", (kernel_ulong_t)&dw8250_dw_apb }, 79962306a36Sopenharmony_ci { "INT3434", (kernel_ulong_t)&dw8250_dw_apb }, 80062306a36Sopenharmony_ci { "INT3435", (kernel_ulong_t)&dw8250_dw_apb }, 80162306a36Sopenharmony_ci { "INTC10EE", (kernel_ulong_t)&dw8250_dw_apb }, 80262306a36Sopenharmony_ci { }, 80362306a36Sopenharmony_ci}; 80462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, dw8250_acpi_match); 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_cistatic struct platform_driver dw8250_platform_driver = { 80762306a36Sopenharmony_ci .driver = { 80862306a36Sopenharmony_ci .name = "dw-apb-uart", 80962306a36Sopenharmony_ci .pm = pm_ptr(&dw8250_pm_ops), 81062306a36Sopenharmony_ci .of_match_table = dw8250_of_match, 81162306a36Sopenharmony_ci .acpi_match_table = dw8250_acpi_match, 81262306a36Sopenharmony_ci }, 81362306a36Sopenharmony_ci .probe = dw8250_probe, 81462306a36Sopenharmony_ci .remove = dw8250_remove, 81562306a36Sopenharmony_ci}; 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_cimodule_platform_driver(dw8250_platform_driver); 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ciMODULE_AUTHOR("Jamie Iles"); 82062306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 82162306a36Sopenharmony_ciMODULE_DESCRIPTION("Synopsys DesignWare 8250 serial port driver"); 82262306a36Sopenharmony_ciMODULE_ALIAS("platform:dw-apb-uart"); 823