xref: /openbmc/linux/drivers/tty/serial/8250/8250_dw.c (revision 278002edb19bce2c628fafb0af936e77000f3a5b)
1e3b3d0f5SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0+
29bef3d41SPaul Gortmaker /*
39bef3d41SPaul Gortmaker  * Synopsys DesignWare 8250 driver.
49bef3d41SPaul Gortmaker  *
59bef3d41SPaul Gortmaker  * Copyright 2011 Picochip, Jamie Iles.
66a7320c4SHeikki Krogerus  * Copyright 2013 Intel Corporation
79bef3d41SPaul Gortmaker  *
89bef3d41SPaul Gortmaker  * The Synopsys DesignWare 8250 has an extra feature whereby it detects if the
99bef3d41SPaul Gortmaker  * LCR is written whilst busy.  If it is, then a busy detect interrupt is
109bef3d41SPaul Gortmaker  * raised, the LCR needs to be rewritten and the uart status register read.
119bef3d41SPaul Gortmaker  */
126343ecd7SAndy Shevchenko #include <linux/clk.h>
13914eaf93SJoshua Scott #include <linux/delay.h>
149bef3d41SPaul Gortmaker #include <linux/device.h>
159bef3d41SPaul Gortmaker #include <linux/io.h>
164088ca3eSAndy Shevchenko #include <linux/mod_devicetable.h>
179bef3d41SPaul Gortmaker #include <linux/module.h>
186343ecd7SAndy Shevchenko #include <linux/notifier.h>
199bef3d41SPaul Gortmaker #include <linux/platform_device.h>
20ffc3ae6dSHeikki Krogerus #include <linux/pm_runtime.h>
216343ecd7SAndy Shevchenko #include <linux/property.h>
226343ecd7SAndy Shevchenko #include <linux/reset.h>
236343ecd7SAndy Shevchenko #include <linux/slab.h>
246343ecd7SAndy Shevchenko #include <linux/workqueue.h>
259bef3d41SPaul Gortmaker 
26d5f1af7eSDavid Daney #include <asm/byteorder.h>
27d5f1af7eSDavid Daney 
286343ecd7SAndy Shevchenko #include <linux/serial_8250.h>
296343ecd7SAndy Shevchenko #include <linux/serial_reg.h>
306343ecd7SAndy Shevchenko 
314d5675c3SAndy Shevchenko #include "8250_dwlib.h"
327277b2a1SHeikki Krogerus 
3330046df2SHeikki Krogerus /* Offsets for the DesignWare specific registers */
3430046df2SHeikki Krogerus #define DW_UART_USR	0x1f /* UART Status Register */
35aa63d786SPhil Edworthy #define DW_UART_DMASA	0xa8 /* DMA Software Ack */
3630046df2SHeikki Krogerus 
37ffd38144SMiquel Raynal #define OCTEON_UART_USR	0x27 /* UART Status Register */
38ffd38144SMiquel Raynal 
39aa63d786SPhil Edworthy #define RZN1_UART_TDMACR 0x10c /* DMA Control Register Transmit Mode */
40aa63d786SPhil Edworthy #define RZN1_UART_RDMACR 0x110 /* DMA Control Register Receive Mode */
41aa63d786SPhil Edworthy 
420e0b989eSEd Blake /* DesignWare specific register fields */
430e0b989eSEd Blake #define DW_UART_MCR_SIRE		BIT(6)
4430046df2SHeikki Krogerus 
45aa63d786SPhil Edworthy /* Renesas specific register fields */
46aa63d786SPhil Edworthy #define RZN1_UART_xDMACR_DMA_EN		BIT(0)
47aa63d786SPhil Edworthy #define RZN1_UART_xDMACR_1_WORD_BURST	(0 << 1)
48aa63d786SPhil Edworthy #define RZN1_UART_xDMACR_4_WORD_BURST	(1 << 1)
49b941e487SBiju Das #define RZN1_UART_xDMACR_8_WORD_BURST	(2 << 1)
50aa63d786SPhil Edworthy #define RZN1_UART_xDMACR_BLK_SZ(x)	((x) << 3)
51aa63d786SPhil Edworthy 
524a218b27SEmil Renner Berthing /* Quirks */
534a218b27SEmil Renner Berthing #define DW_UART_QUIRK_OCTEON		BIT(0)
544a218b27SEmil Renner Berthing #define DW_UART_QUIRK_ARMADA_38X	BIT(1)
554a218b27SEmil Renner Berthing #define DW_UART_QUIRK_SKIP_SET_RATE	BIT(2)
56aa63d786SPhil Edworthy #define DW_UART_QUIRK_IS_DMA_FC		BIT(3)
57836e1a9fSAndy Shevchenko #define DW_UART_QUIRK_APMC0D08		BIT(4)
583a03ef31SAndy Shevchenko #define DW_UART_QUIRK_CPR_VALUE		BIT(5)
594a218b27SEmil Renner Berthing 
6008cfaa12SAndy Shevchenko struct dw8250_platform_data {
6108cfaa12SAndy Shevchenko 	u8 usr_reg;
6208cfaa12SAndy Shevchenko 	u32 cpr_value;
6308cfaa12SAndy Shevchenko 	unsigned int quirks;
6408cfaa12SAndy Shevchenko };
6508cfaa12SAndy Shevchenko 
6608cfaa12SAndy Shevchenko struct dw8250_data {
6708cfaa12SAndy Shevchenko 	struct dw8250_port_data	data;
6808cfaa12SAndy Shevchenko 	const struct dw8250_platform_data *pdata;
6908cfaa12SAndy Shevchenko 
7008cfaa12SAndy Shevchenko 	int			msr_mask_on;
7108cfaa12SAndy Shevchenko 	int			msr_mask_off;
7208cfaa12SAndy Shevchenko 	struct clk		*clk;
7308cfaa12SAndy Shevchenko 	struct clk		*pclk;
7408cfaa12SAndy Shevchenko 	struct notifier_block	clk_notifier;
7508cfaa12SAndy Shevchenko 	struct work_struct	clk_work;
7608cfaa12SAndy Shevchenko 	struct reset_control	*rst;
7708cfaa12SAndy Shevchenko 
7808cfaa12SAndy Shevchenko 	unsigned int		skip_autocfg:1;
7908cfaa12SAndy Shevchenko 	unsigned int		uart_16550_compatible:1;
8008cfaa12SAndy Shevchenko };
8108cfaa12SAndy Shevchenko 
to_dw8250_data(struct dw8250_port_data * data)8208cfaa12SAndy Shevchenko static inline struct dw8250_data *to_dw8250_data(struct dw8250_port_data *data)
8308cfaa12SAndy Shevchenko {
8408cfaa12SAndy Shevchenko 	return container_of(data, struct dw8250_data, data);
8508cfaa12SAndy Shevchenko }
8608cfaa12SAndy Shevchenko 
clk_to_dw8250_data(struct notifier_block * nb)87cc816969SSerge Semin static inline struct dw8250_data *clk_to_dw8250_data(struct notifier_block *nb)
88cc816969SSerge Semin {
89cc816969SSerge Semin 	return container_of(nb, struct dw8250_data, clk_notifier);
90cc816969SSerge Semin }
91cc816969SSerge Semin 
work_to_dw8250_data(struct work_struct * work)92cc816969SSerge Semin static inline struct dw8250_data *work_to_dw8250_data(struct work_struct *work)
93cc816969SSerge Semin {
94cc816969SSerge Semin 	return container_of(work, struct dw8250_data, clk_work);
95cc816969SSerge Semin }
96cc816969SSerge Semin 
dw8250_modify_msr(struct uart_port * p,int offset,int value)9733acbb82STim Kryger static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value)
9833acbb82STim Kryger {
994d5675c3SAndy Shevchenko 	struct dw8250_data *d = to_dw8250_data(p->private_data);
10033acbb82STim Kryger 
101dfd37668SDesmond Liu 	/* Override any modem control signals if needed */
102dfd37668SDesmond Liu 	if (offset == UART_MSR) {
103dfd37668SDesmond Liu 		value |= d->msr_mask_on;
104dfd37668SDesmond Liu 		value &= ~d->msr_mask_off;
105dfd37668SDesmond Liu 	}
106dfd37668SDesmond Liu 
10733acbb82STim Kryger 	return value;
10833acbb82STim Kryger }
10933acbb82STim Kryger 
dw8250_force_idle(struct uart_port * p)110c49436b6STim Kryger static void dw8250_force_idle(struct uart_port *p)
111c49436b6STim Kryger {
112b1261c86SAndy Shevchenko 	struct uart_8250_port *up = up_to_u8250p(p);
1134f4e6703SVAMSHI GAJJELA 	unsigned int lsr;
114b1261c86SAndy Shevchenko 
115b1261c86SAndy Shevchenko 	serial8250_clear_and_reinit_fifos(up);
1164f4e6703SVAMSHI GAJJELA 
1174f4e6703SVAMSHI GAJJELA 	/*
1184f4e6703SVAMSHI GAJJELA 	 * With PSLVERR_RESP_EN parameter set to 1, the device generates an
1194f4e6703SVAMSHI GAJJELA 	 * error response when an attempt to read an empty RBR with FIFO
1204f4e6703SVAMSHI GAJJELA 	 * enabled.
1214f4e6703SVAMSHI GAJJELA 	 */
1224f4e6703SVAMSHI GAJJELA 	if (up->fcr & UART_FCR_ENABLE_FIFO) {
1234f4e6703SVAMSHI GAJJELA 		lsr = p->serial_in(p, UART_LSR);
1244f4e6703SVAMSHI GAJJELA 		if (!(lsr & UART_LSR_DR))
1254f4e6703SVAMSHI GAJJELA 			return;
1264f4e6703SVAMSHI GAJJELA 	}
1274f4e6703SVAMSHI GAJJELA 
128c49436b6STim Kryger 	(void)p->serial_in(p, UART_RX);
129c49436b6STim Kryger }
130c49436b6STim Kryger 
dw8250_check_lcr(struct uart_port * p,int value)131cdcea058SNoam Camus static void dw8250_check_lcr(struct uart_port *p, int value)
1329bef3d41SPaul Gortmaker {
133cdcea058SNoam Camus 	void __iomem *offset = p->membase + (UART_LCR << p->regshift);
134cdcea058SNoam Camus 	int tries = 1000;
135c49436b6STim Kryger 
136c49436b6STim Kryger 	/* Make sure LCR write wasn't ignored */
137c49436b6STim Kryger 	while (tries--) {
1386979f8d2SJames Hogan 		unsigned int lcr = p->serial_in(p, UART_LCR);
139cdcea058SNoam Camus 
1406979f8d2SJames Hogan 		if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR))
141c49436b6STim Kryger 			return;
142cdcea058SNoam Camus 
143c49436b6STim Kryger 		dw8250_force_idle(p);
144cdcea058SNoam Camus 
145cdcea058SNoam Camus #ifdef CONFIG_64BIT
1466550be9fSKefeng Wang 		if (p->type == PORT_OCTEON)
147cdcea058SNoam Camus 			__raw_writeq(value & 0xff, offset);
1486550be9fSKefeng Wang 		else
1496550be9fSKefeng Wang #endif
150cdcea058SNoam Camus 		if (p->iotype == UPIO_MEM32)
151cdcea058SNoam Camus 			writel(value, offset);
1525a43140cSNoam Camus 		else if (p->iotype == UPIO_MEM32BE)
1535a43140cSNoam Camus 			iowrite32be(value, offset);
154cdcea058SNoam Camus 		else
155cdcea058SNoam Camus 			writeb(value, offset);
156c49436b6STim Kryger 	}
1577fd6f640SPeter Hurley 	/*
1587fd6f640SPeter Hurley 	 * FIXME: this deadlocks if port->lock is already held
1597fd6f640SPeter Hurley 	 * dev_err(p->dev, "Couldn't set LCR to %d\n", value);
1607fd6f640SPeter Hurley 	 */
161c49436b6STim Kryger }
162cdcea058SNoam Camus 
163914eaf93SJoshua Scott /* Returns once the transmitter is empty or we run out of retries */
dw8250_tx_wait_empty(struct uart_port * p)164b7639b0bSJoshua Scott static void dw8250_tx_wait_empty(struct uart_port *p)
165914eaf93SJoshua Scott {
166af14f300SIlpo Järvinen 	struct uart_8250_port *up = up_to_u8250p(p);
167b7639b0bSJoshua Scott 	unsigned int tries = 20000;
168b7639b0bSJoshua Scott 	unsigned int delay_threshold = tries - 1000;
169914eaf93SJoshua Scott 	unsigned int lsr;
170914eaf93SJoshua Scott 
171914eaf93SJoshua Scott 	while (tries--) {
172914eaf93SJoshua Scott 		lsr = readb (p->membase + (UART_LSR << p->regshift));
173507bd6fbSIlpo Järvinen 		up->lsr_saved_flags |= lsr & up->lsr_save_mask;
174af14f300SIlpo Järvinen 
175914eaf93SJoshua Scott 		if (lsr & UART_LSR_TEMT)
176914eaf93SJoshua Scott 			break;
177b7639b0bSJoshua Scott 
178b7639b0bSJoshua Scott 		/* The device is first given a chance to empty without delay,
179b7639b0bSJoshua Scott 		 * to avoid slowdowns at high bitrates. If after 1000 tries
180b7639b0bSJoshua Scott 		 * the buffer has still not emptied, allow more time for low-
181b7639b0bSJoshua Scott 		 * speed links. */
182b7639b0bSJoshua Scott 		if (tries < delay_threshold)
183b7639b0bSJoshua Scott 			udelay (1);
184914eaf93SJoshua Scott 	}
185914eaf93SJoshua Scott }
186914eaf93SJoshua Scott 
dw8250_serial_out(struct uart_port * p,int offset,int value)187b7639b0bSJoshua Scott static void dw8250_serial_out(struct uart_port *p, int offset, int value)
188b7639b0bSJoshua Scott {
1894d5675c3SAndy Shevchenko 	struct dw8250_data *d = to_dw8250_data(p->private_data);
190914eaf93SJoshua Scott 
191cdcea058SNoam Camus 	writeb(value, p->membase + (offset << p->regshift));
192cdcea058SNoam Camus 
193cdcea058SNoam Camus 	if (offset == UART_LCR && !d->uart_16550_compatible)
194cdcea058SNoam Camus 		dw8250_check_lcr(p, value);
1959bef3d41SPaul Gortmaker }
1969bef3d41SPaul Gortmaker 
dw8250_serial_out38x(struct uart_port * p,int offset,int value)197309f7bedSIlpo Järvinen static void dw8250_serial_out38x(struct uart_port *p, int offset, int value)
198309f7bedSIlpo Järvinen {
199309f7bedSIlpo Järvinen 	/* Allow the TX to drain before we reconfigure */
200309f7bedSIlpo Järvinen 	if (offset == UART_LCR)
201309f7bedSIlpo Järvinen 		dw8250_tx_wait_empty(p);
202309f7bedSIlpo Järvinen 
203309f7bedSIlpo Järvinen 	dw8250_serial_out(p, offset, value);
204309f7bedSIlpo Järvinen }
205309f7bedSIlpo Järvinen 
dw8250_serial_in(struct uart_port * p,int offset)2069bef3d41SPaul Gortmaker static unsigned int dw8250_serial_in(struct uart_port *p, int offset)
2079bef3d41SPaul Gortmaker {
20833acbb82STim Kryger 	unsigned int value = readb(p->membase + (offset << p->regshift));
2099bef3d41SPaul Gortmaker 
21033acbb82STim Kryger 	return dw8250_modify_msr(p, offset, value);
2119bef3d41SPaul Gortmaker }
2129bef3d41SPaul Gortmaker 
213bca2092dSDavid Daney #ifdef CONFIG_64BIT
dw8250_serial_inq(struct uart_port * p,int offset)214bca2092dSDavid Daney static unsigned int dw8250_serial_inq(struct uart_port *p, int offset)
215d5f1af7eSDavid Daney {
216bca2092dSDavid Daney 	unsigned int value;
217bca2092dSDavid Daney 
218bca2092dSDavid Daney 	value = (u8)__raw_readq(p->membase + (offset << p->regshift));
219bca2092dSDavid Daney 
220bca2092dSDavid Daney 	return dw8250_modify_msr(p, offset, value);
221d5f1af7eSDavid Daney }
222d5f1af7eSDavid Daney 
dw8250_serial_outq(struct uart_port * p,int offset,int value)223bca2092dSDavid Daney static void dw8250_serial_outq(struct uart_port *p, int offset, int value)
224bca2092dSDavid Daney {
2254d5675c3SAndy Shevchenko 	struct dw8250_data *d = to_dw8250_data(p->private_data);
226cdcea058SNoam Camus 
227bca2092dSDavid Daney 	value &= 0xff;
228bca2092dSDavid Daney 	__raw_writeq(value, p->membase + (offset << p->regshift));
229bca2092dSDavid Daney 	/* Read back to ensure register write ordering. */
230bca2092dSDavid Daney 	__raw_readq(p->membase + (UART_LCR << p->regshift));
231bca2092dSDavid Daney 
232cdcea058SNoam Camus 	if (offset == UART_LCR && !d->uart_16550_compatible)
233cdcea058SNoam Camus 		dw8250_check_lcr(p, value);
234bca2092dSDavid Daney }
235bca2092dSDavid Daney #endif /* CONFIG_64BIT */
236bca2092dSDavid Daney 
dw8250_serial_out32(struct uart_port * p,int offset,int value)2379bef3d41SPaul Gortmaker static void dw8250_serial_out32(struct uart_port *p, int offset, int value)
2389bef3d41SPaul Gortmaker {
2394d5675c3SAndy Shevchenko 	struct dw8250_data *d = to_dw8250_data(p->private_data);
240cdcea058SNoam Camus 
24133acbb82STim Kryger 	writel(value, p->membase + (offset << p->regshift));
242c49436b6STim Kryger 
243cdcea058SNoam Camus 	if (offset == UART_LCR && !d->uart_16550_compatible)
244cdcea058SNoam Camus 		dw8250_check_lcr(p, value);
2459bef3d41SPaul Gortmaker }
2469bef3d41SPaul Gortmaker 
dw8250_serial_in32(struct uart_port * p,int offset)2479bef3d41SPaul Gortmaker static unsigned int dw8250_serial_in32(struct uart_port *p, int offset)
2489bef3d41SPaul Gortmaker {
24933acbb82STim Kryger 	unsigned int value = readl(p->membase + (offset << p->regshift));
2509bef3d41SPaul Gortmaker 
25133acbb82STim Kryger 	return dw8250_modify_msr(p, offset, value);
2529bef3d41SPaul Gortmaker }
2539bef3d41SPaul Gortmaker 
dw8250_serial_out32be(struct uart_port * p,int offset,int value)25446250901SNoam Camus static void dw8250_serial_out32be(struct uart_port *p, int offset, int value)
25546250901SNoam Camus {
2564d5675c3SAndy Shevchenko 	struct dw8250_data *d = to_dw8250_data(p->private_data);
25746250901SNoam Camus 
25846250901SNoam Camus 	iowrite32be(value, p->membase + (offset << p->regshift));
25946250901SNoam Camus 
26046250901SNoam Camus 	if (offset == UART_LCR && !d->uart_16550_compatible)
26146250901SNoam Camus 		dw8250_check_lcr(p, value);
26246250901SNoam Camus }
26346250901SNoam Camus 
dw8250_serial_in32be(struct uart_port * p,int offset)26446250901SNoam Camus static unsigned int dw8250_serial_in32be(struct uart_port *p, int offset)
26546250901SNoam Camus {
26646250901SNoam Camus        unsigned int value = ioread32be(p->membase + (offset << p->regshift));
26746250901SNoam Camus 
26846250901SNoam Camus        return dw8250_modify_msr(p, offset, value);
26946250901SNoam Camus }
27046250901SNoam Camus 
27146250901SNoam Camus 
dw8250_handle_irq(struct uart_port * p)2729bef3d41SPaul Gortmaker static int dw8250_handle_irq(struct uart_port *p)
2739bef3d41SPaul Gortmaker {
274424d7918SDouglas Anderson 	struct uart_8250_port *up = up_to_u8250p(p);
2754d5675c3SAndy Shevchenko 	struct dw8250_data *d = to_dw8250_data(p->private_data);
2769bef3d41SPaul Gortmaker 	unsigned int iir = p->serial_in(p, UART_IIR);
2778ef6e1baSMiquel Raynal 	bool rx_timeout = (iir & 0x3f) == UART_IIR_RX_TIMEOUT;
278aa63d786SPhil Edworthy 	unsigned int quirks = d->pdata->quirks;
279424d7918SDouglas Anderson 	unsigned int status;
280424d7918SDouglas Anderson 	unsigned long flags;
281424d7918SDouglas Anderson 
282424d7918SDouglas Anderson 	/*
283424d7918SDouglas Anderson 	 * There are ways to get Designware-based UARTs into a state where
284424d7918SDouglas Anderson 	 * they are asserting UART_IIR_RX_TIMEOUT but there is no actual
285424d7918SDouglas Anderson 	 * data available.  If we see such a case then we'll do a bogus
286424d7918SDouglas Anderson 	 * read.  If we don't do this then the "RX TIMEOUT" interrupt will
287424d7918SDouglas Anderson 	 * fire forever.
288424d7918SDouglas Anderson 	 *
289424d7918SDouglas Anderson 	 * This problem has only been observed so far when not in DMA mode
290424d7918SDouglas Anderson 	 * so we limit the workaround only to non-DMA mode.
291424d7918SDouglas Anderson 	 */
2928ef6e1baSMiquel Raynal 	if (!up->dma && rx_timeout) {
293424d7918SDouglas Anderson 		spin_lock_irqsave(&p->lock, flags);
294197eb5c4SIlpo Järvinen 		status = serial_lsr_in(up);
295424d7918SDouglas Anderson 
296424d7918SDouglas Anderson 		if (!(status & (UART_LSR_DR | UART_LSR_BI)))
297424d7918SDouglas Anderson 			(void) p->serial_in(p, UART_RX);
298424d7918SDouglas Anderson 
299424d7918SDouglas Anderson 		spin_unlock_irqrestore(&p->lock, flags);
300424d7918SDouglas Anderson 	}
3019bef3d41SPaul Gortmaker 
302aa63d786SPhil Edworthy 	/* Manually stop the Rx DMA transfer when acting as flow controller */
303aa63d786SPhil Edworthy 	if (quirks & DW_UART_QUIRK_IS_DMA_FC && up->dma && up->dma->rx_running && rx_timeout) {
304b9491b2eSIlpo Järvinen 		spin_lock_irqsave(&p->lock, flags);
305197eb5c4SIlpo Järvinen 		status = serial_lsr_in(up);
306b9491b2eSIlpo Järvinen 		spin_unlock_irqrestore(&p->lock, flags);
307b9491b2eSIlpo Järvinen 
308aa63d786SPhil Edworthy 		if (status & (UART_LSR_DR | UART_LSR_BI)) {
309aa63d786SPhil Edworthy 			dw8250_writel_ext(p, RZN1_UART_RDMACR, 0);
310aa63d786SPhil Edworthy 			dw8250_writel_ext(p, DW_UART_DMASA, 1);
311aa63d786SPhil Edworthy 		}
312aa63d786SPhil Edworthy 	}
313aa63d786SPhil Edworthy 
31434eefb59SAndy Shevchenko 	if (serial8250_handle_irq(p, iir))
3159bef3d41SPaul Gortmaker 		return 1;
31634eefb59SAndy Shevchenko 
31734eefb59SAndy Shevchenko 	if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
318c49436b6STim Kryger 		/* Clear the USR */
319ffd38144SMiquel Raynal 		(void)p->serial_in(p, d->pdata->usr_reg);
3209bef3d41SPaul Gortmaker 
3219bef3d41SPaul Gortmaker 		return 1;
3229bef3d41SPaul Gortmaker 	}
3239bef3d41SPaul Gortmaker 
3249bef3d41SPaul Gortmaker 	return 0;
3259bef3d41SPaul Gortmaker }
3269bef3d41SPaul Gortmaker 
dw8250_clk_work_cb(struct work_struct * work)327cc816969SSerge Semin static void dw8250_clk_work_cb(struct work_struct *work)
328cc816969SSerge Semin {
329cc816969SSerge Semin 	struct dw8250_data *d = work_to_dw8250_data(work);
330cc816969SSerge Semin 	struct uart_8250_port *up;
331cc816969SSerge Semin 	unsigned long rate;
332cc816969SSerge Semin 
333cc816969SSerge Semin 	rate = clk_get_rate(d->clk);
334cc816969SSerge Semin 	if (rate <= 0)
335cc816969SSerge Semin 		return;
336cc816969SSerge Semin 
337cc816969SSerge Semin 	up = serial8250_get_port(d->data.line);
338cc816969SSerge Semin 
339cc816969SSerge Semin 	serial8250_update_uartclk(&up->port, rate);
340cc816969SSerge Semin }
341cc816969SSerge Semin 
dw8250_clk_notifier_cb(struct notifier_block * nb,unsigned long event,void * data)342cc816969SSerge Semin static int dw8250_clk_notifier_cb(struct notifier_block *nb,
343cc816969SSerge Semin 				  unsigned long event, void *data)
344cc816969SSerge Semin {
345cc816969SSerge Semin 	struct dw8250_data *d = clk_to_dw8250_data(nb);
346cc816969SSerge Semin 
347cc816969SSerge Semin 	/*
348cc816969SSerge Semin 	 * We have no choice but to defer the uartclk update due to two
349cc816969SSerge Semin 	 * deadlocks. First one is caused by a recursive mutex lock which
350cc816969SSerge Semin 	 * happens when clk_set_rate() is called from dw8250_set_termios().
351cc816969SSerge Semin 	 * Second deadlock is more tricky and is caused by an inverted order of
352cc816969SSerge Semin 	 * the clk and tty-port mutexes lock. It happens if clock rate change
353cc816969SSerge Semin 	 * is requested asynchronously while set_termios() is executed between
354cc816969SSerge Semin 	 * tty-port mutex lock and clk_set_rate() function invocation and
355cc816969SSerge Semin 	 * vise-versa. Anyway if we didn't have the reference clock alteration
356cc816969SSerge Semin 	 * in the dw8250_set_termios() method we wouldn't have needed this
357cc816969SSerge Semin 	 * deferred event handling complication.
358cc816969SSerge Semin 	 */
359cc816969SSerge Semin 	if (event == POST_RATE_CHANGE) {
360cc816969SSerge Semin 		queue_work(system_unbound_wq, &d->clk_work);
361cc816969SSerge Semin 		return NOTIFY_OK;
362cc816969SSerge Semin 	}
363cc816969SSerge Semin 
364cc816969SSerge Semin 	return NOTIFY_DONE;
365cc816969SSerge Semin }
366cc816969SSerge Semin 
367ffc3ae6dSHeikki Krogerus static void
dw8250_do_pm(struct uart_port * port,unsigned int state,unsigned int old)368ffc3ae6dSHeikki Krogerus dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
369ffc3ae6dSHeikki Krogerus {
370ffc3ae6dSHeikki Krogerus 	if (!state)
371ffc3ae6dSHeikki Krogerus 		pm_runtime_get_sync(port->dev);
372ffc3ae6dSHeikki Krogerus 
373ffc3ae6dSHeikki Krogerus 	serial8250_do_pm(port, state, old);
374ffc3ae6dSHeikki Krogerus 
375ffc3ae6dSHeikki Krogerus 	if (state)
376ffc3ae6dSHeikki Krogerus 		pm_runtime_put_sync_suspend(port->dev);
377ffc3ae6dSHeikki Krogerus }
378ffc3ae6dSHeikki Krogerus 
dw8250_set_termios(struct uart_port * p,struct ktermios * termios,const struct ktermios * old)3794e26b134SHeikki Krogerus static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
380bec5b814SIlpo Järvinen 			       const struct ktermios *old)
3814e26b134SHeikki Krogerus {
3820be160cfSSerge Semin 	unsigned long newrate = tty_termios_baud_rate(termios) * 16;
3834d5675c3SAndy Shevchenko 	struct dw8250_data *d = to_dw8250_data(p->private_data);
38409498087SHeiko Stuebner 	long rate;
385c14b65feSAndy Shevchenko 	int ret;
3864e26b134SHeikki Krogerus 
3874e26b134SHeikki Krogerus 	clk_disable_unprepare(d->clk);
3880be160cfSSerge Semin 	rate = clk_round_rate(d->clk, newrate);
389442fdef1SSerge Semin 	if (rate > 0) {
390cc816969SSerge Semin 		/*
39174365bc1SJohan Hovold 		 * Note that any clock-notifer worker will block in
39274365bc1SJohan Hovold 		 * serial8250_update_uartclk() until we are done.
393cc816969SSerge Semin 		 */
3940be160cfSSerge Semin 		ret = clk_set_rate(d->clk, newrate);
39574365bc1SJohan Hovold 		if (!ret)
39674365bc1SJohan Hovold 			p->uartclk = rate;
397442fdef1SSerge Semin 	}
3984e26b134SHeikki Krogerus 	clk_prepare_enable(d->clk);
399c14b65feSAndy Shevchenko 
4007c4fc082SAndy Shevchenko 	dw8250_do_set_termios(p, termios, old);
4014e26b134SHeikki Krogerus }
4024e26b134SHeikki Krogerus 
dw8250_set_ldisc(struct uart_port * p,struct ktermios * termios)4030e0b989eSEd Blake static void dw8250_set_ldisc(struct uart_port *p, struct ktermios *termios)
4040e0b989eSEd Blake {
4050e0b989eSEd Blake 	struct uart_8250_port *up = up_to_u8250p(p);
4060e0b989eSEd Blake 	unsigned int mcr = p->serial_in(p, UART_MCR);
4070e0b989eSEd Blake 
4080e0b989eSEd Blake 	if (up->capabilities & UART_CAP_IRDA) {
4090e0b989eSEd Blake 		if (termios->c_line == N_IRDA)
4100e0b989eSEd Blake 			mcr |= DW_UART_MCR_SIRE;
4110e0b989eSEd Blake 		else
4120e0b989eSEd Blake 			mcr &= ~DW_UART_MCR_SIRE;
4130e0b989eSEd Blake 
4140e0b989eSEd Blake 		p->serial_out(p, UART_MCR, mcr);
4150e0b989eSEd Blake 	}
4160e0b989eSEd Blake 	serial8250_do_set_ldisc(p, termios);
4170e0b989eSEd Blake }
4180e0b989eSEd Blake 
4191edb3cf2SHeikki Krogerus /*
4201edb3cf2SHeikki Krogerus  * dw8250_fallback_dma_filter will prevent the UART from getting just any free
4211edb3cf2SHeikki Krogerus  * channel on platforms that have DMA engines, but don't have any channels
4221edb3cf2SHeikki Krogerus  * assigned to the UART.
4231edb3cf2SHeikki Krogerus  *
4241edb3cf2SHeikki Krogerus  * REVISIT: This is a work around for limitation in the DMA Engine API. Once the
4251edb3cf2SHeikki Krogerus  * core problem is fixed, this function is no longer needed.
4261edb3cf2SHeikki Krogerus  */
dw8250_fallback_dma_filter(struct dma_chan * chan,void * param)4271edb3cf2SHeikki Krogerus static bool dw8250_fallback_dma_filter(struct dma_chan *chan, void *param)
4287fb8c56cSHeikki Krogerus {
4299a1870ceSAndy Shevchenko 	return false;
4307fb8c56cSHeikki Krogerus }
4317fb8c56cSHeikki Krogerus 
dw8250_idma_filter(struct dma_chan * chan,void * param)4320788c39bSHeikki Krogerus static bool dw8250_idma_filter(struct dma_chan *chan, void *param)
4330788c39bSHeikki Krogerus {
4345ba846b1SAndy Shevchenko 	return param == chan->device->dev;
4350788c39bSHeikki Krogerus }
4360788c39bSHeikki Krogerus 
dw8250_rzn1_get_dmacr_burst(int max_burst)437aa63d786SPhil Edworthy static u32 dw8250_rzn1_get_dmacr_burst(int max_burst)
438aa63d786SPhil Edworthy {
439aa63d786SPhil Edworthy 	if (max_burst >= 8)
440aa63d786SPhil Edworthy 		return RZN1_UART_xDMACR_8_WORD_BURST;
441aa63d786SPhil Edworthy 	else if (max_burst >= 4)
442aa63d786SPhil Edworthy 		return RZN1_UART_xDMACR_4_WORD_BURST;
443aa63d786SPhil Edworthy 	else
444aa63d786SPhil Edworthy 		return RZN1_UART_xDMACR_1_WORD_BURST;
445aa63d786SPhil Edworthy }
446aa63d786SPhil Edworthy 
dw8250_prepare_tx_dma(struct uart_8250_port * p)447aa63d786SPhil Edworthy static void dw8250_prepare_tx_dma(struct uart_8250_port *p)
448aa63d786SPhil Edworthy {
449aa63d786SPhil Edworthy 	struct uart_port *up = &p->port;
450aa63d786SPhil Edworthy 	struct uart_8250_dma *dma = p->dma;
451aa63d786SPhil Edworthy 	u32 val;
452aa63d786SPhil Edworthy 
453aa63d786SPhil Edworthy 	dw8250_writel_ext(up, RZN1_UART_TDMACR, 0);
454aa63d786SPhil Edworthy 	val = dw8250_rzn1_get_dmacr_burst(dma->txconf.dst_maxburst) |
455aa63d786SPhil Edworthy 	      RZN1_UART_xDMACR_BLK_SZ(dma->tx_size) |
456aa63d786SPhil Edworthy 	      RZN1_UART_xDMACR_DMA_EN;
457aa63d786SPhil Edworthy 	dw8250_writel_ext(up, RZN1_UART_TDMACR, val);
458aa63d786SPhil Edworthy }
459aa63d786SPhil Edworthy 
dw8250_prepare_rx_dma(struct uart_8250_port * p)460aa63d786SPhil Edworthy static void dw8250_prepare_rx_dma(struct uart_8250_port *p)
461aa63d786SPhil Edworthy {
462aa63d786SPhil Edworthy 	struct uart_port *up = &p->port;
463aa63d786SPhil Edworthy 	struct uart_8250_dma *dma = p->dma;
464aa63d786SPhil Edworthy 	u32 val;
465aa63d786SPhil Edworthy 
466aa63d786SPhil Edworthy 	dw8250_writel_ext(up, RZN1_UART_RDMACR, 0);
467aa63d786SPhil Edworthy 	val = dw8250_rzn1_get_dmacr_burst(dma->rxconf.src_maxburst) |
468aa63d786SPhil Edworthy 	      RZN1_UART_xDMACR_BLK_SZ(dma->rx_size) |
469aa63d786SPhil Edworthy 	      RZN1_UART_xDMACR_DMA_EN;
470aa63d786SPhil Edworthy 	dw8250_writel_ext(up, RZN1_UART_RDMACR, val);
471aa63d786SPhil Edworthy }
472aa63d786SPhil Edworthy 
dw8250_quirks(struct uart_port * p,struct dw8250_data * data)4739e08fa50SHeikki Krogerus static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
474d5f1af7eSDavid Daney {
475836e1a9fSAndy Shevchenko 	unsigned int quirks = data->pdata ? data->pdata->quirks : 0;
4763a03ef31SAndy Shevchenko 	u32 cpr_value = data->pdata ? data->pdata->cpr_value : 0;
4773a03ef31SAndy Shevchenko 
4783a03ef31SAndy Shevchenko 	if (quirks & DW_UART_QUIRK_CPR_VALUE)
4793a03ef31SAndy Shevchenko 		data->data.cpr_value = cpr_value;
480d5f1af7eSDavid Daney 
4819e08fa50SHeikki Krogerus #ifdef CONFIG_64BIT
4824a218b27SEmil Renner Berthing 	if (quirks & DW_UART_QUIRK_OCTEON) {
4839e08fa50SHeikki Krogerus 		p->serial_in = dw8250_serial_inq;
4849e08fa50SHeikki Krogerus 		p->serial_out = dw8250_serial_outq;
4859e08fa50SHeikki Krogerus 		p->flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
4869e08fa50SHeikki Krogerus 		p->type = PORT_OCTEON;
4879e08fa50SHeikki Krogerus 		data->skip_autocfg = true;
4889e08fa50SHeikki Krogerus 	}
4899e08fa50SHeikki Krogerus #endif
4900946efc2SAndy Shevchenko 
4914a218b27SEmil Renner Berthing 	if (quirks & DW_UART_QUIRK_ARMADA_38X)
492b7639b0bSJoshua Scott 		p->serial_out = dw8250_serial_out38x;
4934a218b27SEmil Renner Berthing 	if (quirks & DW_UART_QUIRK_SKIP_SET_RATE)
494b0ad20a3SEmil Renner Berthing 		p->set_termios = dw8250_do_set_termios;
495aa63d786SPhil Edworthy 	if (quirks & DW_UART_QUIRK_IS_DMA_FC) {
496aa63d786SPhil Edworthy 		data->data.dma.txconf.device_fc = 1;
497aa63d786SPhil Edworthy 		data->data.dma.rxconf.device_fc = 1;
498aa63d786SPhil Edworthy 		data->data.dma.prepare_tx_dma = dw8250_prepare_tx_dma;
499aa63d786SPhil Edworthy 		data->data.dma.prepare_rx_dma = dw8250_prepare_rx_dma;
500aa63d786SPhil Edworthy 	}
501836e1a9fSAndy Shevchenko 	if (quirks & DW_UART_QUIRK_APMC0D08) {
502d5f1af7eSDavid Daney 		p->iotype = UPIO_MEM32;
5039e08fa50SHeikki Krogerus 		p->regshift = 2;
504d5f1af7eSDavid Daney 		p->serial_in = dw8250_serial_in32;
505c73942e2SHeikki Krogerus 		data->uart_16550_compatible = true;
5060788c39bSHeikki Krogerus 	}
507d5f1af7eSDavid Daney 
5085ba846b1SAndy Shevchenko 	/* Platforms with iDMA 64-bit */
5099e08fa50SHeikki Krogerus 	if (platform_get_resource_byname(to_platform_device(p->dev),
5109e08fa50SHeikki Krogerus 					 IORESOURCE_MEM, "lpss_priv")) {
5114d5675c3SAndy Shevchenko 		data->data.dma.rx_param = p->dev->parent;
5124d5675c3SAndy Shevchenko 		data->data.dma.tx_param = p->dev->parent;
5134d5675c3SAndy Shevchenko 		data->data.dma.fn = dw8250_idma_filter;
5149e08fa50SHeikki Krogerus 	}
515d5f1af7eSDavid Daney }
516d5f1af7eSDavid Daney 
dw8250_clk_disable_unprepare(void * data)517295b0912SAndy Shevchenko static void dw8250_clk_disable_unprepare(void *data)
518295b0912SAndy Shevchenko {
519295b0912SAndy Shevchenko 	clk_disable_unprepare(data);
520295b0912SAndy Shevchenko }
521295b0912SAndy Shevchenko 
dw8250_reset_control_assert(void * data)522295b0912SAndy Shevchenko static void dw8250_reset_control_assert(void *data)
523295b0912SAndy Shevchenko {
524295b0912SAndy Shevchenko 	reset_control_assert(data);
525295b0912SAndy Shevchenko }
526295b0912SAndy Shevchenko 
dw8250_probe(struct platform_device * pdev)5279671f099SBill Pemberton static int dw8250_probe(struct platform_device *pdev)
5289bef3d41SPaul Gortmaker {
52962907e90SAndy Shevchenko 	struct uart_8250_port uart = {}, *up = &uart;
53062907e90SAndy Shevchenko 	struct uart_port *p = &up->port;
5312cb78eabSKefeng Wang 	struct device *dev = &pdev->dev;
5329bef3d41SPaul Gortmaker 	struct dw8250_data *data;
53357f83e5dSAndy Shevchenko 	struct resource *regs;
534a7260c8cSHeikki Krogerus 	int err;
5359bef3d41SPaul Gortmaker 
53657f83e5dSAndy Shevchenko 	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
53757f83e5dSAndy Shevchenko 	if (!regs)
53857f83e5dSAndy Shevchenko 		return dev_err_probe(dev, -EINVAL, "no registers defined\n");
5399bef3d41SPaul Gortmaker 
54078d3da75SHeikki Krogerus 	spin_lock_init(&p->lock);
54178d3da75SHeikki Krogerus 	p->handle_irq	= dw8250_handle_irq;
54278d3da75SHeikki Krogerus 	p->pm		= dw8250_do_pm;
54378d3da75SHeikki Krogerus 	p->type		= PORT_8250;
5441d98b6a0SAndy Shevchenko 	p->flags	= UPF_FIXED_PORT;
5452cb78eabSKefeng Wang 	p->dev		= dev;
5460e0b989eSEd Blake 	p->set_ldisc	= dw8250_set_ldisc;
5476a171b29SJason Uy 	p->set_termios	= dw8250_set_termios;
5489bef3d41SPaul Gortmaker 
5492cb78eabSKefeng Wang 	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
550e302cd93SEmilio López 	if (!data)
551e302cd93SEmilio López 		return -ENOMEM;
552e302cd93SEmilio López 
5534d5675c3SAndy Shevchenko 	data->data.dma.fn = dw8250_fallback_dma_filter;
5544a218b27SEmil Renner Berthing 	data->pdata = device_get_match_data(p->dev);
5554d5675c3SAndy Shevchenko 	p->private_data = &data->data;
55623f5b3fdSHeikki Krogerus 
5572cb78eabSKefeng Wang 	data->uart_16550_compatible = device_property_read_bool(dev,
558c73942e2SHeikki Krogerus 						"snps,uart-16550-compatible");
559c73942e2SHeikki Krogerus 
5601d98b6a0SAndy Shevchenko 	p->mapbase = regs->start;
5611d98b6a0SAndy Shevchenko 	p->mapsize = resource_size(regs);
5621bd8edbaSHeikki Krogerus 
5631d98b6a0SAndy Shevchenko 	p->membase = devm_ioremap(dev, p->mapbase, p->mapsize);
5641d98b6a0SAndy Shevchenko 	if (!p->membase)
5651d98b6a0SAndy Shevchenko 		return -ENOMEM;
5661d98b6a0SAndy Shevchenko 
5671d98b6a0SAndy Shevchenko 	err = uart_read_port_properties(p);
5681d98b6a0SAndy Shevchenko 	/* no interrupt -> fall back to polling */
5691d98b6a0SAndy Shevchenko 	if (err == -ENXIO)
5701d98b6a0SAndy Shevchenko 		err = 0;
5711d98b6a0SAndy Shevchenko 	if (err)
5721d98b6a0SAndy Shevchenko 		return err;
5731d98b6a0SAndy Shevchenko 
5741d98b6a0SAndy Shevchenko 	switch (p->iotype) {
5751d98b6a0SAndy Shevchenko 	case UPIO_MEM:
5761d98b6a0SAndy Shevchenko 		p->serial_in = dw8250_serial_in;
5771d98b6a0SAndy Shevchenko 		p->serial_out = dw8250_serial_out;
5781d98b6a0SAndy Shevchenko 		break;
5791d98b6a0SAndy Shevchenko 	case UPIO_MEM32:
5801bd8edbaSHeikki Krogerus 		p->serial_in = dw8250_serial_in32;
5811bd8edbaSHeikki Krogerus 		p->serial_out = dw8250_serial_out32;
5821d98b6a0SAndy Shevchenko 		break;
5831d98b6a0SAndy Shevchenko 	case UPIO_MEM32BE:
5841d98b6a0SAndy Shevchenko 		p->serial_in = dw8250_serial_in32be;
5851d98b6a0SAndy Shevchenko 		p->serial_out = dw8250_serial_out32be;
5861d98b6a0SAndy Shevchenko 		break;
5871d98b6a0SAndy Shevchenko 	default:
5881d98b6a0SAndy Shevchenko 		return -ENODEV;
5891bd8edbaSHeikki Krogerus 	}
5901bd8edbaSHeikki Krogerus 
5912cb78eabSKefeng Wang 	if (device_property_read_bool(dev, "dcd-override")) {
5921bd8edbaSHeikki Krogerus 		/* Always report DCD as active */
5931bd8edbaSHeikki Krogerus 		data->msr_mask_on |= UART_MSR_DCD;
5941bd8edbaSHeikki Krogerus 		data->msr_mask_off |= UART_MSR_DDCD;
5951bd8edbaSHeikki Krogerus 	}
5961bd8edbaSHeikki Krogerus 
5972cb78eabSKefeng Wang 	if (device_property_read_bool(dev, "dsr-override")) {
5981bd8edbaSHeikki Krogerus 		/* Always report DSR as active */
5991bd8edbaSHeikki Krogerus 		data->msr_mask_on |= UART_MSR_DSR;
6001bd8edbaSHeikki Krogerus 		data->msr_mask_off |= UART_MSR_DDSR;
6011bd8edbaSHeikki Krogerus 	}
6021bd8edbaSHeikki Krogerus 
6032cb78eabSKefeng Wang 	if (device_property_read_bool(dev, "cts-override")) {
6041bd8edbaSHeikki Krogerus 		/* Always report CTS as active */
6051bd8edbaSHeikki Krogerus 		data->msr_mask_on |= UART_MSR_CTS;
6061bd8edbaSHeikki Krogerus 		data->msr_mask_off |= UART_MSR_DCTS;
6071bd8edbaSHeikki Krogerus 	}
6081bd8edbaSHeikki Krogerus 
6092cb78eabSKefeng Wang 	if (device_property_read_bool(dev, "ri-override")) {
6101bd8edbaSHeikki Krogerus 		/* Always report Ring indicator as inactive */
6111bd8edbaSHeikki Krogerus 		data->msr_mask_off |= UART_MSR_RI;
6121bd8edbaSHeikki Krogerus 		data->msr_mask_off |= UART_MSR_TERI;
6131bd8edbaSHeikki Krogerus 	}
6141bd8edbaSHeikki Krogerus 
61523f5b3fdSHeikki Krogerus 	/* If there is separate baudclk, get the rate from it. */
616a8afc193SAndy Shevchenko 	data->clk = devm_clk_get_optional(dev, "baudclk");
617a8afc193SAndy Shevchenko 	if (data->clk == NULL)
618a8afc193SAndy Shevchenko 		data->clk = devm_clk_get_optional(dev, NULL);
619a8afc193SAndy Shevchenko 	if (IS_ERR(data->clk))
620a8afc193SAndy Shevchenko 		return PTR_ERR(data->clk);
621a8afc193SAndy Shevchenko 
622cc816969SSerge Semin 	INIT_WORK(&data->clk_work, dw8250_clk_work_cb);
623cc816969SSerge Semin 	data->clk_notifier.notifier_call = dw8250_clk_notifier_cb;
624cc816969SSerge Semin 
6257d78cbefSHeiko Stübner 	err = clk_prepare_enable(data->clk);
6267d78cbefSHeiko Stübner 	if (err)
62757f83e5dSAndy Shevchenko 		return dev_err_probe(dev, err, "could not enable optional baudclk\n");
628a8afc193SAndy Shevchenko 
629295b0912SAndy Shevchenko 	err = devm_add_action_or_reset(dev, dw8250_clk_disable_unprepare, data->clk);
630295b0912SAndy Shevchenko 	if (err)
631295b0912SAndy Shevchenko 		return err;
632295b0912SAndy Shevchenko 
633a8afc193SAndy Shevchenko 	if (data->clk)
63478d3da75SHeikki Krogerus 		p->uartclk = clk_get_rate(data->clk);
635e302cd93SEmilio López 
63623f5b3fdSHeikki Krogerus 	/* If no clock rate is defined, fail. */
63757f83e5dSAndy Shevchenko 	if (!p->uartclk)
63857f83e5dSAndy Shevchenko 		return dev_err_probe(dev, -EINVAL, "clock rate not defined\n");
63923f5b3fdSHeikki Krogerus 
640a8afc193SAndy Shevchenko 	data->pclk = devm_clk_get_optional(dev, "apb_pclk");
641295b0912SAndy Shevchenko 	if (IS_ERR(data->pclk))
642295b0912SAndy Shevchenko 		return PTR_ERR(data->pclk);
643a8afc193SAndy Shevchenko 
6447d78cbefSHeiko Stübner 	err = clk_prepare_enable(data->pclk);
64557f83e5dSAndy Shevchenko 	if (err)
64657f83e5dSAndy Shevchenko 		return dev_err_probe(dev, err, "could not enable apb_pclk\n");
6477d78cbefSHeiko Stübner 
648295b0912SAndy Shevchenko 	err = devm_add_action_or_reset(dev, dw8250_clk_disable_unprepare, data->pclk);
649295b0912SAndy Shevchenko 	if (err)
650295b0912SAndy Shevchenko 		return err;
651295b0912SAndy Shevchenko 
652b382f5d3SPhilipp Zabel 	data->rst = devm_reset_control_get_optional_exclusive(dev, NULL);
653295b0912SAndy Shevchenko 	if (IS_ERR(data->rst))
654295b0912SAndy Shevchenko 		return PTR_ERR(data->rst);
655295b0912SAndy Shevchenko 
6567fe090bfSChen-Yu Tsai 	reset_control_deassert(data->rst);
6577fe090bfSChen-Yu Tsai 
658295b0912SAndy Shevchenko 	err = devm_add_action_or_reset(dev, dw8250_reset_control_assert, data->rst);
659295b0912SAndy Shevchenko 	if (err)
660295b0912SAndy Shevchenko 		return err;
661295b0912SAndy Shevchenko 
6629e08fa50SHeikki Krogerus 	dw8250_quirks(p, data);
6639bef3d41SPaul Gortmaker 
664c73942e2SHeikki Krogerus 	/* If the Busy Functionality is not implemented, don't handle it */
665cdcea058SNoam Camus 	if (data->uart_16550_compatible)
666c73942e2SHeikki Krogerus 		p->handle_irq = NULL;
667c73942e2SHeikki Krogerus 
6684f042054SHeikki Krogerus 	if (!data->skip_autocfg)
6692338a75eSHeikki Krogerus 		dw8250_setup_port(p);
6704f042054SHeikki Krogerus 
6712559318cSHeikki Krogerus 	/* If we have a valid fifosize, try hooking up DMA */
6722559318cSHeikki Krogerus 	if (p->fifosize) {
6734d5675c3SAndy Shevchenko 		data->data.dma.rxconf.src_maxburst = p->fifosize / 4;
6744d5675c3SAndy Shevchenko 		data->data.dma.txconf.dst_maxburst = p->fifosize / 4;
6754d5675c3SAndy Shevchenko 		up->dma = &data->data.dma;
6762559318cSHeikki Krogerus 	}
6772559318cSHeikki Krogerus 
6784d5675c3SAndy Shevchenko 	data->data.line = serial8250_register_8250_port(up);
679295b0912SAndy Shevchenko 	if (data->data.line < 0)
680295b0912SAndy Shevchenko 		return data->data.line;
6819bef3d41SPaul Gortmaker 
68285985a3dSSerge Semin 	/*
68385985a3dSSerge Semin 	 * Some platforms may provide a reference clock shared between several
68485985a3dSSerge Semin 	 * devices. In this case any clock state change must be known to the
68585985a3dSSerge Semin 	 * UART port at least post factum.
68685985a3dSSerge Semin 	 */
68785985a3dSSerge Semin 	if (data->clk) {
68885985a3dSSerge Semin 		err = clk_notifier_register(data->clk, &data->clk_notifier);
68985985a3dSSerge Semin 		if (err)
69057f83e5dSAndy Shevchenko 			return dev_err_probe(dev, err, "Failed to set the clock notifier\n");
69185985a3dSSerge Semin 		queue_work(system_unbound_wq, &data->clk_work);
69285985a3dSSerge Semin 	}
69385985a3dSSerge Semin 
6949bef3d41SPaul Gortmaker 	platform_set_drvdata(pdev, data);
6959bef3d41SPaul Gortmaker 
6962cb78eabSKefeng Wang 	pm_runtime_set_active(dev);
6972cb78eabSKefeng Wang 	pm_runtime_enable(dev);
698ffc3ae6dSHeikki Krogerus 
6999bef3d41SPaul Gortmaker 	return 0;
7009bef3d41SPaul Gortmaker }
7019bef3d41SPaul Gortmaker 
dw8250_remove(struct platform_device * pdev)702ae8d8a14SBill Pemberton static int dw8250_remove(struct platform_device *pdev)
7039bef3d41SPaul Gortmaker {
7049bef3d41SPaul Gortmaker 	struct dw8250_data *data = platform_get_drvdata(pdev);
705a8571fdaSAndy Shevchenko 	struct device *dev = &pdev->dev;
7069bef3d41SPaul Gortmaker 
707a8571fdaSAndy Shevchenko 	pm_runtime_get_sync(dev);
708ffc3ae6dSHeikki Krogerus 
70985985a3dSSerge Semin 	if (data->clk) {
71085985a3dSSerge Semin 		clk_notifier_unregister(data->clk, &data->clk_notifier);
71185985a3dSSerge Semin 
71285985a3dSSerge Semin 		flush_work(&data->clk_work);
71385985a3dSSerge Semin 	}
71485985a3dSSerge Semin 
7154d5675c3SAndy Shevchenko 	serial8250_unregister_port(data->data.line);
7169bef3d41SPaul Gortmaker 
717a8571fdaSAndy Shevchenko 	pm_runtime_disable(dev);
718a8571fdaSAndy Shevchenko 	pm_runtime_put_noidle(dev);
719ffc3ae6dSHeikki Krogerus 
7209bef3d41SPaul Gortmaker 	return 0;
7219bef3d41SPaul Gortmaker }
7229bef3d41SPaul Gortmaker 
dw8250_suspend(struct device * dev)723ffc3ae6dSHeikki Krogerus static int dw8250_suspend(struct device *dev)
724b61c5ed5SJames Hogan {
725ffc3ae6dSHeikki Krogerus 	struct dw8250_data *data = dev_get_drvdata(dev);
726b61c5ed5SJames Hogan 
7274d5675c3SAndy Shevchenko 	serial8250_suspend_port(data->data.line);
728b61c5ed5SJames Hogan 
729b61c5ed5SJames Hogan 	return 0;
730b61c5ed5SJames Hogan }
731b61c5ed5SJames Hogan 
dw8250_resume(struct device * dev)732ffc3ae6dSHeikki Krogerus static int dw8250_resume(struct device *dev)
733b61c5ed5SJames Hogan {
734ffc3ae6dSHeikki Krogerus 	struct dw8250_data *data = dev_get_drvdata(dev);
735b61c5ed5SJames Hogan 
7364d5675c3SAndy Shevchenko 	serial8250_resume_port(data->data.line);
737b61c5ed5SJames Hogan 
738b61c5ed5SJames Hogan 	return 0;
739b61c5ed5SJames Hogan }
740b61c5ed5SJames Hogan 
dw8250_runtime_suspend(struct device * dev)741ffc3ae6dSHeikki Krogerus static int dw8250_runtime_suspend(struct device *dev)
742ffc3ae6dSHeikki Krogerus {
743ffc3ae6dSHeikki Krogerus 	struct dw8250_data *data = dev_get_drvdata(dev);
744ffc3ae6dSHeikki Krogerus 
745ffc3ae6dSHeikki Krogerus 	clk_disable_unprepare(data->clk);
746ffc3ae6dSHeikki Krogerus 
7477d78cbefSHeiko Stübner 	clk_disable_unprepare(data->pclk);
7487d78cbefSHeiko Stübner 
749ffc3ae6dSHeikki Krogerus 	return 0;
750ffc3ae6dSHeikki Krogerus }
751ffc3ae6dSHeikki Krogerus 
dw8250_runtime_resume(struct device * dev)752ffc3ae6dSHeikki Krogerus static int dw8250_runtime_resume(struct device *dev)
753ffc3ae6dSHeikki Krogerus {
754ffc3ae6dSHeikki Krogerus 	struct dw8250_data *data = dev_get_drvdata(dev);
755ffc3ae6dSHeikki Krogerus 
7567d78cbefSHeiko Stübner 	clk_prepare_enable(data->pclk);
7577d78cbefSHeiko Stübner 
758ffc3ae6dSHeikki Krogerus 	clk_prepare_enable(data->clk);
759ffc3ae6dSHeikki Krogerus 
760ffc3ae6dSHeikki Krogerus 	return 0;
761ffc3ae6dSHeikki Krogerus }
762ffc3ae6dSHeikki Krogerus 
763ffc3ae6dSHeikki Krogerus static const struct dev_pm_ops dw8250_pm_ops = {
764808313bcSAndy Shevchenko 	SYSTEM_SLEEP_PM_OPS(dw8250_suspend, dw8250_resume)
765808313bcSAndy Shevchenko 	RUNTIME_PM_OPS(dw8250_runtime_suspend, dw8250_runtime_resume, NULL)
766ffc3ae6dSHeikki Krogerus };
767ffc3ae6dSHeikki Krogerus 
7684a218b27SEmil Renner Berthing static const struct dw8250_platform_data dw8250_dw_apb = {
769ffd38144SMiquel Raynal 	.usr_reg = DW_UART_USR,
7704a218b27SEmil Renner Berthing };
7714a218b27SEmil Renner Berthing 
7724a218b27SEmil Renner Berthing static const struct dw8250_platform_data dw8250_octeon_3860_data = {
773ffd38144SMiquel Raynal 	.usr_reg = OCTEON_UART_USR,
7744a218b27SEmil Renner Berthing 	.quirks = DW_UART_QUIRK_OCTEON,
7754a218b27SEmil Renner Berthing };
7764a218b27SEmil Renner Berthing 
7774a218b27SEmil Renner Berthing static const struct dw8250_platform_data dw8250_armada_38x_data = {
778ffd38144SMiquel Raynal 	.usr_reg = DW_UART_USR,
7794a218b27SEmil Renner Berthing 	.quirks = DW_UART_QUIRK_ARMADA_38X,
7804a218b27SEmil Renner Berthing };
7814a218b27SEmil Renner Berthing 
7824a218b27SEmil Renner Berthing static const struct dw8250_platform_data dw8250_renesas_rzn1_data = {
783ffd38144SMiquel Raynal 	.usr_reg = DW_UART_USR,
7843a03ef31SAndy Shevchenko 	.cpr_value = 0x00012f32,
7853a03ef31SAndy Shevchenko 	.quirks = DW_UART_QUIRK_CPR_VALUE | DW_UART_QUIRK_IS_DMA_FC,
7864a218b27SEmil Renner Berthing };
7874a218b27SEmil Renner Berthing 
788*b32ce4f9SInochi Amaoto static const struct dw8250_platform_data dw8250_skip_set_rate_data = {
789ffd38144SMiquel Raynal 	.usr_reg = DW_UART_USR,
7904a218b27SEmil Renner Berthing 	.quirks = DW_UART_QUIRK_SKIP_SET_RATE,
7914a218b27SEmil Renner Berthing };
7924a218b27SEmil Renner Berthing 
793a7260c8cSHeikki Krogerus static const struct of_device_id dw8250_of_match[] = {
7944a218b27SEmil Renner Berthing 	{ .compatible = "snps,dw-apb-uart", .data = &dw8250_dw_apb },
7954a218b27SEmil Renner Berthing 	{ .compatible = "cavium,octeon-3860-uart", .data = &dw8250_octeon_3860_data },
7964a218b27SEmil Renner Berthing 	{ .compatible = "marvell,armada-38x-uart", .data = &dw8250_armada_38x_data },
7974a218b27SEmil Renner Berthing 	{ .compatible = "renesas,rzn1-uart", .data = &dw8250_renesas_rzn1_data },
798*b32ce4f9SInochi Amaoto 	{ .compatible = "sophgo,sg2044-uart", .data = &dw8250_skip_set_rate_data },
799*b32ce4f9SInochi Amaoto 	{ .compatible = "starfive,jh7100-uart", .data = &dw8250_skip_set_rate_data },
8009bef3d41SPaul Gortmaker 	{ /* Sentinel */ }
8019bef3d41SPaul Gortmaker };
802a7260c8cSHeikki Krogerus MODULE_DEVICE_TABLE(of, dw8250_of_match);
8039bef3d41SPaul Gortmaker 
804836e1a9fSAndy Shevchenko static const struct dw8250_platform_data dw8250_apmc0d08 = {
805836e1a9fSAndy Shevchenko 	.usr_reg = DW_UART_USR,
806836e1a9fSAndy Shevchenko 	.quirks = DW_UART_QUIRK_APMC0D08,
807836e1a9fSAndy Shevchenko };
808836e1a9fSAndy Shevchenko 
8096a7320c4SHeikki Krogerus static const struct acpi_device_id dw8250_acpi_match[] = {
810cd16044dSMarcin Wojtas 	{ "80860F0A", (kernel_ulong_t)&dw8250_dw_apb },
811cd16044dSMarcin Wojtas 	{ "8086228A", (kernel_ulong_t)&dw8250_dw_apb },
812cd16044dSMarcin Wojtas 	{ "AMD0020", (kernel_ulong_t)&dw8250_dw_apb },
813cd16044dSMarcin Wojtas 	{ "AMDI0020", (kernel_ulong_t)&dw8250_dw_apb },
814cd16044dSMarcin Wojtas 	{ "AMDI0022", (kernel_ulong_t)&dw8250_dw_apb },
815836e1a9fSAndy Shevchenko 	{ "APMC0D08", (kernel_ulong_t)&dw8250_apmc0d08 },
816cd16044dSMarcin Wojtas 	{ "BRCM2032", (kernel_ulong_t)&dw8250_dw_apb },
817cd16044dSMarcin Wojtas 	{ "HISI0031", (kernel_ulong_t)&dw8250_dw_apb },
818cd16044dSMarcin Wojtas 	{ "INT33C4", (kernel_ulong_t)&dw8250_dw_apb },
819cd16044dSMarcin Wojtas 	{ "INT33C5", (kernel_ulong_t)&dw8250_dw_apb },
820cd16044dSMarcin Wojtas 	{ "INT3434", (kernel_ulong_t)&dw8250_dw_apb },
821cd16044dSMarcin Wojtas 	{ "INT3435", (kernel_ulong_t)&dw8250_dw_apb },
822977a60f0SAndy Shevchenko 	{ "INTC10EE", (kernel_ulong_t)&dw8250_dw_apb },
8236a7320c4SHeikki Krogerus 	{ },
8246a7320c4SHeikki Krogerus };
8256a7320c4SHeikki Krogerus MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match);
8266a7320c4SHeikki Krogerus 
8279bef3d41SPaul Gortmaker static struct platform_driver dw8250_platform_driver = {
8289bef3d41SPaul Gortmaker 	.driver = {
8299bef3d41SPaul Gortmaker 		.name		= "dw-apb-uart",
830808313bcSAndy Shevchenko 		.pm		= pm_ptr(&dw8250_pm_ops),
831a7260c8cSHeikki Krogerus 		.of_match_table	= dw8250_of_match,
832ebabb77aSAndy Shevchenko 		.acpi_match_table = dw8250_acpi_match,
8339bef3d41SPaul Gortmaker 	},
8349bef3d41SPaul Gortmaker 	.probe			= dw8250_probe,
8352d47b716SBill Pemberton 	.remove			= dw8250_remove,
8369bef3d41SPaul Gortmaker };
8379bef3d41SPaul Gortmaker 
8389bef3d41SPaul Gortmaker module_platform_driver(dw8250_platform_driver);
8399bef3d41SPaul Gortmaker 
8409bef3d41SPaul Gortmaker MODULE_AUTHOR("Jamie Iles");
8419bef3d41SPaul Gortmaker MODULE_LICENSE("GPL");
8429bef3d41SPaul Gortmaker MODULE_DESCRIPTION("Synopsys DesignWare 8250 serial port driver");
843f3ac3fc2SMika Westerberg MODULE_ALIAS("platform:dw-apb-uart");
844