xref: /linux/drivers/tty/serial/8250/8250_dw.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
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)
57173b097dSAndy Shevchenko #define DW_UART_QUIRK_APMC0D08		BIT(4)
5887d80bfbSAndy Shevchenko #define DW_UART_QUIRK_CPR_VALUE		BIT(5)
594a218b27SEmil Renner Berthing 
602c945120SAndy Shevchenko struct dw8250_platform_data {
612c945120SAndy Shevchenko 	u8 usr_reg;
622c945120SAndy Shevchenko 	u32 cpr_value;
632c945120SAndy Shevchenko 	unsigned int quirks;
642c945120SAndy Shevchenko };
652c945120SAndy Shevchenko 
662c945120SAndy Shevchenko struct dw8250_data {
672c945120SAndy Shevchenko 	struct dw8250_port_data	data;
682c945120SAndy Shevchenko 	const struct dw8250_platform_data *pdata;
692c945120SAndy Shevchenko 
702c945120SAndy Shevchenko 	int			msr_mask_on;
712c945120SAndy Shevchenko 	int			msr_mask_off;
722c945120SAndy Shevchenko 	struct clk		*clk;
732c945120SAndy Shevchenko 	struct clk		*pclk;
742c945120SAndy Shevchenko 	struct notifier_block	clk_notifier;
752c945120SAndy Shevchenko 	struct work_struct	clk_work;
762c945120SAndy Shevchenko 	struct reset_control	*rst;
772c945120SAndy Shevchenko 
782c945120SAndy Shevchenko 	unsigned int		skip_autocfg:1;
792c945120SAndy Shevchenko 	unsigned int		uart_16550_compatible:1;
802c945120SAndy Shevchenko };
812c945120SAndy Shevchenko 
to_dw8250_data(struct dw8250_port_data * data)822c945120SAndy Shevchenko static inline struct dw8250_data *to_dw8250_data(struct dw8250_port_data *data)
832c945120SAndy Shevchenko {
842c945120SAndy Shevchenko 	return container_of(data, struct dw8250_data, data);
852c945120SAndy Shevchenko }
862c945120SAndy 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 offset,int value)1316a533ed7SAndy Shevchenko static void dw8250_check_lcr(struct uart_port *p, int offset, int value)
1329bef3d41SPaul Gortmaker {
1336a533ed7SAndy Shevchenko 	struct dw8250_data *d = to_dw8250_data(p->private_data);
1346a533ed7SAndy Shevchenko 	void __iomem *addr = p->membase + (offset << p->regshift);
135cdcea058SNoam Camus 	int tries = 1000;
136c49436b6STim Kryger 
1376a533ed7SAndy Shevchenko 	if (offset != UART_LCR || d->uart_16550_compatible)
1386a533ed7SAndy Shevchenko 		return;
1396a533ed7SAndy Shevchenko 
140c49436b6STim Kryger 	/* Make sure LCR write wasn't ignored */
141c49436b6STim Kryger 	while (tries--) {
1426a533ed7SAndy Shevchenko 		unsigned int lcr = p->serial_in(p, offset);
143cdcea058SNoam Camus 
1446979f8d2SJames Hogan 		if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR))
145c49436b6STim Kryger 			return;
146cdcea058SNoam Camus 
147c49436b6STim Kryger 		dw8250_force_idle(p);
148cdcea058SNoam Camus 
149cdcea058SNoam Camus #ifdef CONFIG_64BIT
1506550be9fSKefeng Wang 		if (p->type == PORT_OCTEON)
1516a533ed7SAndy Shevchenko 			__raw_writeq(value & 0xff, addr);
1526550be9fSKefeng Wang 		else
1536550be9fSKefeng Wang #endif
154cdcea058SNoam Camus 		if (p->iotype == UPIO_MEM32)
1556a533ed7SAndy Shevchenko 			writel(value, addr);
1565a43140cSNoam Camus 		else if (p->iotype == UPIO_MEM32BE)
1576a533ed7SAndy Shevchenko 			iowrite32be(value, addr);
158cdcea058SNoam Camus 		else
1596a533ed7SAndy Shevchenko 			writeb(value, addr);
160c49436b6STim Kryger 	}
1617fd6f640SPeter Hurley 	/*
1627fd6f640SPeter Hurley 	 * FIXME: this deadlocks if port->lock is already held
1637fd6f640SPeter Hurley 	 * dev_err(p->dev, "Couldn't set LCR to %d\n", value);
1647fd6f640SPeter Hurley 	 */
165c49436b6STim Kryger }
166cdcea058SNoam Camus 
167914eaf93SJoshua Scott /* Returns once the transmitter is empty or we run out of retries */
dw8250_tx_wait_empty(struct uart_port * p)168b7639b0bSJoshua Scott static void dw8250_tx_wait_empty(struct uart_port *p)
169914eaf93SJoshua Scott {
170af14f300SIlpo Järvinen 	struct uart_8250_port *up = up_to_u8250p(p);
171b7639b0bSJoshua Scott 	unsigned int tries = 20000;
172b7639b0bSJoshua Scott 	unsigned int delay_threshold = tries - 1000;
173914eaf93SJoshua Scott 	unsigned int lsr;
174914eaf93SJoshua Scott 
175914eaf93SJoshua Scott 	while (tries--) {
176914eaf93SJoshua Scott 		lsr = readb (p->membase + (UART_LSR << p->regshift));
177507bd6fbSIlpo Järvinen 		up->lsr_saved_flags |= lsr & up->lsr_save_mask;
178af14f300SIlpo Järvinen 
179914eaf93SJoshua Scott 		if (lsr & UART_LSR_TEMT)
180914eaf93SJoshua Scott 			break;
181b7639b0bSJoshua Scott 
182b7639b0bSJoshua Scott 		/* The device is first given a chance to empty without delay,
183b7639b0bSJoshua Scott 		 * to avoid slowdowns at high bitrates. If after 1000 tries
184b7639b0bSJoshua Scott 		 * the buffer has still not emptied, allow more time for low-
185b7639b0bSJoshua Scott 		 * speed links. */
186b7639b0bSJoshua Scott 		if (tries < delay_threshold)
187b7639b0bSJoshua Scott 			udelay (1);
188914eaf93SJoshua Scott 	}
189914eaf93SJoshua Scott }
190914eaf93SJoshua Scott 
dw8250_serial_out(struct uart_port * p,int offset,int value)191b7639b0bSJoshua Scott static void dw8250_serial_out(struct uart_port *p, int offset, int value)
192b7639b0bSJoshua Scott {
193cdcea058SNoam Camus 	writeb(value, p->membase + (offset << p->regshift));
1946a533ed7SAndy Shevchenko 	dw8250_check_lcr(p, offset, 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 {
216c205edcdSAndy Shevchenko 	u8 value = __raw_readq(p->membase + (offset << p->regshift));
217bca2092dSDavid Daney 
218bca2092dSDavid Daney 	return dw8250_modify_msr(p, offset, value);
219d5f1af7eSDavid Daney }
220d5f1af7eSDavid Daney 
dw8250_serial_outq(struct uart_port * p,int offset,int value)221bca2092dSDavid Daney static void dw8250_serial_outq(struct uart_port *p, int offset, int value)
222bca2092dSDavid Daney {
223bca2092dSDavid Daney 	value &= 0xff;
224bca2092dSDavid Daney 	__raw_writeq(value, p->membase + (offset << p->regshift));
225bca2092dSDavid Daney 	/* Read back to ensure register write ordering. */
226bca2092dSDavid Daney 	__raw_readq(p->membase + (UART_LCR << p->regshift));
227bca2092dSDavid Daney 
2286a533ed7SAndy Shevchenko 	dw8250_check_lcr(p, offset, value);
229bca2092dSDavid Daney }
230bca2092dSDavid Daney #endif /* CONFIG_64BIT */
231bca2092dSDavid Daney 
dw8250_serial_out32(struct uart_port * p,int offset,int value)2329bef3d41SPaul Gortmaker static void dw8250_serial_out32(struct uart_port *p, int offset, int value)
2339bef3d41SPaul Gortmaker {
23433acbb82STim Kryger 	writel(value, p->membase + (offset << p->regshift));
2356a533ed7SAndy Shevchenko 	dw8250_check_lcr(p, offset, value);
2369bef3d41SPaul Gortmaker }
2379bef3d41SPaul Gortmaker 
dw8250_serial_in32(struct uart_port * p,int offset)2389bef3d41SPaul Gortmaker static unsigned int dw8250_serial_in32(struct uart_port *p, int offset)
2399bef3d41SPaul Gortmaker {
24033acbb82STim Kryger 	unsigned int value = readl(p->membase + (offset << p->regshift));
2419bef3d41SPaul Gortmaker 
24233acbb82STim Kryger 	return dw8250_modify_msr(p, offset, value);
2439bef3d41SPaul Gortmaker }
2449bef3d41SPaul Gortmaker 
dw8250_serial_out32be(struct uart_port * p,int offset,int value)24546250901SNoam Camus static void dw8250_serial_out32be(struct uart_port *p, int offset, int value)
24646250901SNoam Camus {
24746250901SNoam Camus 	iowrite32be(value, p->membase + (offset << p->regshift));
2486a533ed7SAndy Shevchenko 	dw8250_check_lcr(p, offset, value);
24946250901SNoam Camus }
25046250901SNoam Camus 
dw8250_serial_in32be(struct uart_port * p,int offset)25146250901SNoam Camus static unsigned int dw8250_serial_in32be(struct uart_port *p, int offset)
25246250901SNoam Camus {
25346250901SNoam Camus        unsigned int value = ioread32be(p->membase + (offset << p->regshift));
25446250901SNoam Camus 
25546250901SNoam Camus        return dw8250_modify_msr(p, offset, value);
25646250901SNoam Camus }
25746250901SNoam Camus 
25846250901SNoam Camus 
dw8250_handle_irq(struct uart_port * p)2599bef3d41SPaul Gortmaker static int dw8250_handle_irq(struct uart_port *p)
2609bef3d41SPaul Gortmaker {
261424d7918SDouglas Anderson 	struct uart_8250_port *up = up_to_u8250p(p);
2624d5675c3SAndy Shevchenko 	struct dw8250_data *d = to_dw8250_data(p->private_data);
2639bef3d41SPaul Gortmaker 	unsigned int iir = p->serial_in(p, UART_IIR);
2648ef6e1baSMiquel Raynal 	bool rx_timeout = (iir & 0x3f) == UART_IIR_RX_TIMEOUT;
265aa63d786SPhil Edworthy 	unsigned int quirks = d->pdata->quirks;
266424d7918SDouglas Anderson 	unsigned int status;
267424d7918SDouglas Anderson 	unsigned long flags;
268424d7918SDouglas Anderson 
269424d7918SDouglas Anderson 	/*
270424d7918SDouglas Anderson 	 * There are ways to get Designware-based UARTs into a state where
271424d7918SDouglas Anderson 	 * they are asserting UART_IIR_RX_TIMEOUT but there is no actual
272424d7918SDouglas Anderson 	 * data available.  If we see such a case then we'll do a bogus
273424d7918SDouglas Anderson 	 * read.  If we don't do this then the "RX TIMEOUT" interrupt will
274424d7918SDouglas Anderson 	 * fire forever.
275424d7918SDouglas Anderson 	 *
276424d7918SDouglas Anderson 	 * This problem has only been observed so far when not in DMA mode
277424d7918SDouglas Anderson 	 * so we limit the workaround only to non-DMA mode.
278424d7918SDouglas Anderson 	 */
2798ef6e1baSMiquel Raynal 	if (!up->dma && rx_timeout) {
280fdc5d7a4SThomas Gleixner 		uart_port_lock_irqsave(p, &flags);
281197eb5c4SIlpo Järvinen 		status = serial_lsr_in(up);
282424d7918SDouglas Anderson 
283424d7918SDouglas Anderson 		if (!(status & (UART_LSR_DR | UART_LSR_BI)))
284424d7918SDouglas Anderson 			(void) p->serial_in(p, UART_RX);
285424d7918SDouglas Anderson 
286fdc5d7a4SThomas Gleixner 		uart_port_unlock_irqrestore(p, flags);
287424d7918SDouglas Anderson 	}
2889bef3d41SPaul Gortmaker 
289aa63d786SPhil Edworthy 	/* Manually stop the Rx DMA transfer when acting as flow controller */
290aa63d786SPhil Edworthy 	if (quirks & DW_UART_QUIRK_IS_DMA_FC && up->dma && up->dma->rx_running && rx_timeout) {
291fdc5d7a4SThomas Gleixner 		uart_port_lock_irqsave(p, &flags);
292197eb5c4SIlpo Järvinen 		status = serial_lsr_in(up);
293fdc5d7a4SThomas Gleixner 		uart_port_unlock_irqrestore(p, flags);
294b9491b2eSIlpo Järvinen 
295aa63d786SPhil Edworthy 		if (status & (UART_LSR_DR | UART_LSR_BI)) {
296aa63d786SPhil Edworthy 			dw8250_writel_ext(p, RZN1_UART_RDMACR, 0);
297aa63d786SPhil Edworthy 			dw8250_writel_ext(p, DW_UART_DMASA, 1);
298aa63d786SPhil Edworthy 		}
299aa63d786SPhil Edworthy 	}
300aa63d786SPhil Edworthy 
30134eefb59SAndy Shevchenko 	if (serial8250_handle_irq(p, iir))
3029bef3d41SPaul Gortmaker 		return 1;
30334eefb59SAndy Shevchenko 
30434eefb59SAndy Shevchenko 	if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
305c49436b6STim Kryger 		/* Clear the USR */
306ffd38144SMiquel Raynal 		(void)p->serial_in(p, d->pdata->usr_reg);
3079bef3d41SPaul Gortmaker 
3089bef3d41SPaul Gortmaker 		return 1;
3099bef3d41SPaul Gortmaker 	}
3109bef3d41SPaul Gortmaker 
3119bef3d41SPaul Gortmaker 	return 0;
3129bef3d41SPaul Gortmaker }
3139bef3d41SPaul Gortmaker 
dw8250_clk_work_cb(struct work_struct * work)314cc816969SSerge Semin static void dw8250_clk_work_cb(struct work_struct *work)
315cc816969SSerge Semin {
316cc816969SSerge Semin 	struct dw8250_data *d = work_to_dw8250_data(work);
317cc816969SSerge Semin 	struct uart_8250_port *up;
318cc816969SSerge Semin 	unsigned long rate;
319cc816969SSerge Semin 
320cc816969SSerge Semin 	rate = clk_get_rate(d->clk);
321cc816969SSerge Semin 	if (rate <= 0)
322cc816969SSerge Semin 		return;
323cc816969SSerge Semin 
324cc816969SSerge Semin 	up = serial8250_get_port(d->data.line);
325cc816969SSerge Semin 
326cc816969SSerge Semin 	serial8250_update_uartclk(&up->port, rate);
327cc816969SSerge Semin }
328cc816969SSerge Semin 
dw8250_clk_notifier_cb(struct notifier_block * nb,unsigned long event,void * data)329cc816969SSerge Semin static int dw8250_clk_notifier_cb(struct notifier_block *nb,
330cc816969SSerge Semin 				  unsigned long event, void *data)
331cc816969SSerge Semin {
332cc816969SSerge Semin 	struct dw8250_data *d = clk_to_dw8250_data(nb);
333cc816969SSerge Semin 
334cc816969SSerge Semin 	/*
335cc816969SSerge Semin 	 * We have no choice but to defer the uartclk update due to two
336cc816969SSerge Semin 	 * deadlocks. First one is caused by a recursive mutex lock which
337cc816969SSerge Semin 	 * happens when clk_set_rate() is called from dw8250_set_termios().
338cc816969SSerge Semin 	 * Second deadlock is more tricky and is caused by an inverted order of
339cc816969SSerge Semin 	 * the clk and tty-port mutexes lock. It happens if clock rate change
340cc816969SSerge Semin 	 * is requested asynchronously while set_termios() is executed between
341cc816969SSerge Semin 	 * tty-port mutex lock and clk_set_rate() function invocation and
342cc816969SSerge Semin 	 * vise-versa. Anyway if we didn't have the reference clock alteration
343cc816969SSerge Semin 	 * in the dw8250_set_termios() method we wouldn't have needed this
344cc816969SSerge Semin 	 * deferred event handling complication.
345cc816969SSerge Semin 	 */
346cc816969SSerge Semin 	if (event == POST_RATE_CHANGE) {
347cc816969SSerge Semin 		queue_work(system_unbound_wq, &d->clk_work);
348cc816969SSerge Semin 		return NOTIFY_OK;
349cc816969SSerge Semin 	}
350cc816969SSerge Semin 
351cc816969SSerge Semin 	return NOTIFY_DONE;
352cc816969SSerge Semin }
353cc816969SSerge Semin 
354ffc3ae6dSHeikki Krogerus static void
dw8250_do_pm(struct uart_port * port,unsigned int state,unsigned int old)355ffc3ae6dSHeikki Krogerus dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
356ffc3ae6dSHeikki Krogerus {
357ffc3ae6dSHeikki Krogerus 	if (!state)
358ffc3ae6dSHeikki Krogerus 		pm_runtime_get_sync(port->dev);
359ffc3ae6dSHeikki Krogerus 
360ffc3ae6dSHeikki Krogerus 	serial8250_do_pm(port, state, old);
361ffc3ae6dSHeikki Krogerus 
362ffc3ae6dSHeikki Krogerus 	if (state)
363ffc3ae6dSHeikki Krogerus 		pm_runtime_put_sync_suspend(port->dev);
364ffc3ae6dSHeikki Krogerus }
365ffc3ae6dSHeikki Krogerus 
dw8250_set_termios(struct uart_port * p,struct ktermios * termios,const struct ktermios * old)3664e26b134SHeikki Krogerus static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
367bec5b814SIlpo Järvinen 			       const struct ktermios *old)
3684e26b134SHeikki Krogerus {
3690be160cfSSerge Semin 	unsigned long newrate = tty_termios_baud_rate(termios) * 16;
3704d5675c3SAndy Shevchenko 	struct dw8250_data *d = to_dw8250_data(p->private_data);
37109498087SHeiko Stuebner 	long rate;
372c14b65feSAndy Shevchenko 	int ret;
3734e26b134SHeikki Krogerus 
374e5d6bd25SPeter Collingbourne 	clk_disable_unprepare(d->clk);
3757dfae6cbSHans de Goede 	rate = clk_round_rate(d->clk, newrate);
3767dfae6cbSHans de Goede 	if (rate > 0) {
377cc816969SSerge Semin 		/*
37874365bc1SJohan Hovold 		 * Note that any clock-notifer worker will block in
37974365bc1SJohan Hovold 		 * serial8250_update_uartclk() until we are done.
380cc816969SSerge Semin 		 */
3810be160cfSSerge Semin 		ret = clk_set_rate(d->clk, newrate);
38274365bc1SJohan Hovold 		if (!ret)
38374365bc1SJohan Hovold 			p->uartclk = rate;
384e5d6bd25SPeter Collingbourne 	}
3857dfae6cbSHans de Goede 	clk_prepare_enable(d->clk);
386c14b65feSAndy Shevchenko 
3877c4fc082SAndy Shevchenko 	dw8250_do_set_termios(p, termios, old);
3884e26b134SHeikki Krogerus }
3894e26b134SHeikki Krogerus 
dw8250_set_ldisc(struct uart_port * p,struct ktermios * termios)3900e0b989eSEd Blake static void dw8250_set_ldisc(struct uart_port *p, struct ktermios *termios)
3910e0b989eSEd Blake {
3920e0b989eSEd Blake 	struct uart_8250_port *up = up_to_u8250p(p);
3930e0b989eSEd Blake 	unsigned int mcr = p->serial_in(p, UART_MCR);
3940e0b989eSEd Blake 
3950e0b989eSEd Blake 	if (up->capabilities & UART_CAP_IRDA) {
3960e0b989eSEd Blake 		if (termios->c_line == N_IRDA)
3970e0b989eSEd Blake 			mcr |= DW_UART_MCR_SIRE;
3980e0b989eSEd Blake 		else
3990e0b989eSEd Blake 			mcr &= ~DW_UART_MCR_SIRE;
4000e0b989eSEd Blake 
4010e0b989eSEd Blake 		p->serial_out(p, UART_MCR, mcr);
4020e0b989eSEd Blake 	}
4030e0b989eSEd Blake 	serial8250_do_set_ldisc(p, termios);
4040e0b989eSEd Blake }
4050e0b989eSEd Blake 
4061edb3cf2SHeikki Krogerus /*
4071edb3cf2SHeikki Krogerus  * dw8250_fallback_dma_filter will prevent the UART from getting just any free
4081edb3cf2SHeikki Krogerus  * channel on platforms that have DMA engines, but don't have any channels
4091edb3cf2SHeikki Krogerus  * assigned to the UART.
4101edb3cf2SHeikki Krogerus  *
4111edb3cf2SHeikki Krogerus  * REVISIT: This is a work around for limitation in the DMA Engine API. Once the
4121edb3cf2SHeikki Krogerus  * core problem is fixed, this function is no longer needed.
4131edb3cf2SHeikki Krogerus  */
dw8250_fallback_dma_filter(struct dma_chan * chan,void * param)4141edb3cf2SHeikki Krogerus static bool dw8250_fallback_dma_filter(struct dma_chan *chan, void *param)
4157fb8c56cSHeikki Krogerus {
4169a1870ceSAndy Shevchenko 	return false;
4177fb8c56cSHeikki Krogerus }
4187fb8c56cSHeikki Krogerus 
dw8250_idma_filter(struct dma_chan * chan,void * param)4190788c39bSHeikki Krogerus static bool dw8250_idma_filter(struct dma_chan *chan, void *param)
4200788c39bSHeikki Krogerus {
4215ba846b1SAndy Shevchenko 	return param == chan->device->dev;
4220788c39bSHeikki Krogerus }
4230788c39bSHeikki Krogerus 
dw8250_rzn1_get_dmacr_burst(int max_burst)424aa63d786SPhil Edworthy static u32 dw8250_rzn1_get_dmacr_burst(int max_burst)
425aa63d786SPhil Edworthy {
426aa63d786SPhil Edworthy 	if (max_burst >= 8)
427aa63d786SPhil Edworthy 		return RZN1_UART_xDMACR_8_WORD_BURST;
428aa63d786SPhil Edworthy 	else if (max_burst >= 4)
429aa63d786SPhil Edworthy 		return RZN1_UART_xDMACR_4_WORD_BURST;
430aa63d786SPhil Edworthy 	else
431aa63d786SPhil Edworthy 		return RZN1_UART_xDMACR_1_WORD_BURST;
432aa63d786SPhil Edworthy }
433aa63d786SPhil Edworthy 
dw8250_prepare_tx_dma(struct uart_8250_port * p)434aa63d786SPhil Edworthy static void dw8250_prepare_tx_dma(struct uart_8250_port *p)
435aa63d786SPhil Edworthy {
436aa63d786SPhil Edworthy 	struct uart_port *up = &p->port;
437aa63d786SPhil Edworthy 	struct uart_8250_dma *dma = p->dma;
438aa63d786SPhil Edworthy 	u32 val;
439aa63d786SPhil Edworthy 
440aa63d786SPhil Edworthy 	dw8250_writel_ext(up, RZN1_UART_TDMACR, 0);
441aa63d786SPhil Edworthy 	val = dw8250_rzn1_get_dmacr_burst(dma->txconf.dst_maxburst) |
442aa63d786SPhil Edworthy 	      RZN1_UART_xDMACR_BLK_SZ(dma->tx_size) |
443aa63d786SPhil Edworthy 	      RZN1_UART_xDMACR_DMA_EN;
444aa63d786SPhil Edworthy 	dw8250_writel_ext(up, RZN1_UART_TDMACR, val);
445aa63d786SPhil Edworthy }
446aa63d786SPhil Edworthy 
dw8250_prepare_rx_dma(struct uart_8250_port * p)447aa63d786SPhil Edworthy static void dw8250_prepare_rx_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_RDMACR, 0);
454aa63d786SPhil Edworthy 	val = dw8250_rzn1_get_dmacr_burst(dma->rxconf.src_maxburst) |
455aa63d786SPhil Edworthy 	      RZN1_UART_xDMACR_BLK_SZ(dma->rx_size) |
456aa63d786SPhil Edworthy 	      RZN1_UART_xDMACR_DMA_EN;
457aa63d786SPhil Edworthy 	dw8250_writel_ext(up, RZN1_UART_RDMACR, val);
458aa63d786SPhil Edworthy }
459aa63d786SPhil Edworthy 
dw8250_quirks(struct uart_port * p,struct dw8250_data * data)4609e08fa50SHeikki Krogerus static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
461d5f1af7eSDavid Daney {
462173b097dSAndy Shevchenko 	unsigned int quirks = data->pdata ? data->pdata->quirks : 0;
46387d80bfbSAndy Shevchenko 	u32 cpr_value = data->pdata ? data->pdata->cpr_value : 0;
46487d80bfbSAndy Shevchenko 
46587d80bfbSAndy Shevchenko 	if (quirks & DW_UART_QUIRK_CPR_VALUE)
46687d80bfbSAndy Shevchenko 		data->data.cpr_value = cpr_value;
4670946efc2SAndy Shevchenko 
4689e08fa50SHeikki Krogerus #ifdef CONFIG_64BIT
4694a218b27SEmil Renner Berthing 	if (quirks & DW_UART_QUIRK_OCTEON) {
4709e08fa50SHeikki Krogerus 		p->serial_in = dw8250_serial_inq;
4719e08fa50SHeikki Krogerus 		p->serial_out = dw8250_serial_outq;
4729e08fa50SHeikki Krogerus 		p->flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
4739e08fa50SHeikki Krogerus 		p->type = PORT_OCTEON;
4749e08fa50SHeikki Krogerus 		data->skip_autocfg = true;
4759e08fa50SHeikki Krogerus 	}
4769e08fa50SHeikki Krogerus #endif
4770946efc2SAndy Shevchenko 
4784a218b27SEmil Renner Berthing 	if (quirks & DW_UART_QUIRK_ARMADA_38X)
479b7639b0bSJoshua Scott 		p->serial_out = dw8250_serial_out38x;
4804a218b27SEmil Renner Berthing 	if (quirks & DW_UART_QUIRK_SKIP_SET_RATE)
481b0ad20a3SEmil Renner Berthing 		p->set_termios = dw8250_do_set_termios;
482aa63d786SPhil Edworthy 	if (quirks & DW_UART_QUIRK_IS_DMA_FC) {
483aa63d786SPhil Edworthy 		data->data.dma.txconf.device_fc = 1;
484aa63d786SPhil Edworthy 		data->data.dma.rxconf.device_fc = 1;
485aa63d786SPhil Edworthy 		data->data.dma.prepare_tx_dma = dw8250_prepare_tx_dma;
486aa63d786SPhil Edworthy 		data->data.dma.prepare_rx_dma = dw8250_prepare_rx_dma;
487aa63d786SPhil Edworthy 	}
488173b097dSAndy Shevchenko 	if (quirks & DW_UART_QUIRK_APMC0D08) {
489d5f1af7eSDavid Daney 		p->iotype = UPIO_MEM32;
4909e08fa50SHeikki Krogerus 		p->regshift = 2;
491d5f1af7eSDavid Daney 		p->serial_in = dw8250_serial_in32;
492c73942e2SHeikki Krogerus 		data->uart_16550_compatible = true;
4930788c39bSHeikki Krogerus 	}
494d5f1af7eSDavid Daney 
4955ba846b1SAndy Shevchenko 	/* Platforms with iDMA 64-bit */
4969e08fa50SHeikki Krogerus 	if (platform_get_resource_byname(to_platform_device(p->dev),
4979e08fa50SHeikki Krogerus 					 IORESOURCE_MEM, "lpss_priv")) {
4984d5675c3SAndy Shevchenko 		data->data.dma.rx_param = p->dev->parent;
4994d5675c3SAndy Shevchenko 		data->data.dma.tx_param = p->dev->parent;
5004d5675c3SAndy Shevchenko 		data->data.dma.fn = dw8250_idma_filter;
5019e08fa50SHeikki Krogerus 	}
502d5f1af7eSDavid Daney }
503d5f1af7eSDavid Daney 
dw8250_reset_control_assert(void * data)504295b0912SAndy Shevchenko static void dw8250_reset_control_assert(void *data)
505295b0912SAndy Shevchenko {
506295b0912SAndy Shevchenko 	reset_control_assert(data);
507295b0912SAndy Shevchenko }
508295b0912SAndy Shevchenko 
dw8250_probe(struct platform_device * pdev)5099671f099SBill Pemberton static int dw8250_probe(struct platform_device *pdev)
5109bef3d41SPaul Gortmaker {
51162907e90SAndy Shevchenko 	struct uart_8250_port uart = {}, *up = &uart;
51262907e90SAndy Shevchenko 	struct uart_port *p = &up->port;
5132cb78eabSKefeng Wang 	struct device *dev = &pdev->dev;
5149bef3d41SPaul Gortmaker 	struct dw8250_data *data;
51557f83e5dSAndy Shevchenko 	struct resource *regs;
516a7260c8cSHeikki Krogerus 	int err;
5179bef3d41SPaul Gortmaker 
51857f83e5dSAndy Shevchenko 	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
51957f83e5dSAndy Shevchenko 	if (!regs)
52057f83e5dSAndy Shevchenko 		return dev_err_probe(dev, -EINVAL, "no registers defined\n");
5219bef3d41SPaul Gortmaker 
52278d3da75SHeikki Krogerus 	spin_lock_init(&p->lock);
52378d3da75SHeikki Krogerus 	p->handle_irq	= dw8250_handle_irq;
52478d3da75SHeikki Krogerus 	p->pm		= dw8250_do_pm;
52578d3da75SHeikki Krogerus 	p->type		= PORT_8250;
526e6a46d07SAndy Shevchenko 	p->flags	= UPF_FIXED_PORT;
5272cb78eabSKefeng Wang 	p->dev		= dev;
5280e0b989eSEd Blake 	p->set_ldisc	= dw8250_set_ldisc;
5296a171b29SJason Uy 	p->set_termios	= dw8250_set_termios;
5309bef3d41SPaul Gortmaker 
5312cb78eabSKefeng Wang 	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
532e302cd93SEmilio López 	if (!data)
533e302cd93SEmilio López 		return -ENOMEM;
534e302cd93SEmilio López 
5354d5675c3SAndy Shevchenko 	data->data.dma.fn = dw8250_fallback_dma_filter;
5364a218b27SEmil Renner Berthing 	data->pdata = device_get_match_data(p->dev);
5374d5675c3SAndy Shevchenko 	p->private_data = &data->data;
53823f5b3fdSHeikki Krogerus 
5392cb78eabSKefeng Wang 	data->uart_16550_compatible = device_property_read_bool(dev,
540c73942e2SHeikki Krogerus 						"snps,uart-16550-compatible");
541c73942e2SHeikki Krogerus 
542e6a46d07SAndy Shevchenko 	p->mapbase = regs->start;
543e6a46d07SAndy Shevchenko 	p->mapsize = resource_size(regs);
5441bd8edbaSHeikki Krogerus 
545e6a46d07SAndy Shevchenko 	p->membase = devm_ioremap(dev, p->mapbase, p->mapsize);
546e6a46d07SAndy Shevchenko 	if (!p->membase)
547e6a46d07SAndy Shevchenko 		return -ENOMEM;
548e6a46d07SAndy Shevchenko 
549e6a46d07SAndy Shevchenko 	err = uart_read_port_properties(p);
550e6a46d07SAndy Shevchenko 	/* no interrupt -> fall back to polling */
551e6a46d07SAndy Shevchenko 	if (err == -ENXIO)
552e6a46d07SAndy Shevchenko 		err = 0;
553e6a46d07SAndy Shevchenko 	if (err)
554e6a46d07SAndy Shevchenko 		return err;
555e6a46d07SAndy Shevchenko 
556e6a46d07SAndy Shevchenko 	switch (p->iotype) {
557e6a46d07SAndy Shevchenko 	case UPIO_MEM:
558e6a46d07SAndy Shevchenko 		p->serial_in = dw8250_serial_in;
559e6a46d07SAndy Shevchenko 		p->serial_out = dw8250_serial_out;
560e6a46d07SAndy Shevchenko 		break;
561e6a46d07SAndy Shevchenko 	case UPIO_MEM32:
5621bd8edbaSHeikki Krogerus 		p->serial_in = dw8250_serial_in32;
5631bd8edbaSHeikki Krogerus 		p->serial_out = dw8250_serial_out32;
564e6a46d07SAndy Shevchenko 		break;
565e6a46d07SAndy Shevchenko 	case UPIO_MEM32BE:
566e6a46d07SAndy Shevchenko 		p->serial_in = dw8250_serial_in32be;
567e6a46d07SAndy Shevchenko 		p->serial_out = dw8250_serial_out32be;
568e6a46d07SAndy Shevchenko 		break;
569e6a46d07SAndy Shevchenko 	default:
570e6a46d07SAndy Shevchenko 		return -ENODEV;
5711bd8edbaSHeikki Krogerus 	}
5721bd8edbaSHeikki Krogerus 
5732cb78eabSKefeng Wang 	if (device_property_read_bool(dev, "dcd-override")) {
5741bd8edbaSHeikki Krogerus 		/* Always report DCD as active */
5751bd8edbaSHeikki Krogerus 		data->msr_mask_on |= UART_MSR_DCD;
5761bd8edbaSHeikki Krogerus 		data->msr_mask_off |= UART_MSR_DDCD;
5771bd8edbaSHeikki Krogerus 	}
5781bd8edbaSHeikki Krogerus 
5792cb78eabSKefeng Wang 	if (device_property_read_bool(dev, "dsr-override")) {
5801bd8edbaSHeikki Krogerus 		/* Always report DSR as active */
5811bd8edbaSHeikki Krogerus 		data->msr_mask_on |= UART_MSR_DSR;
5821bd8edbaSHeikki Krogerus 		data->msr_mask_off |= UART_MSR_DDSR;
5831bd8edbaSHeikki Krogerus 	}
5841bd8edbaSHeikki Krogerus 
5852cb78eabSKefeng Wang 	if (device_property_read_bool(dev, "cts-override")) {
5861bd8edbaSHeikki Krogerus 		/* Always report CTS as active */
5871bd8edbaSHeikki Krogerus 		data->msr_mask_on |= UART_MSR_CTS;
5881bd8edbaSHeikki Krogerus 		data->msr_mask_off |= UART_MSR_DCTS;
5891bd8edbaSHeikki Krogerus 	}
5901bd8edbaSHeikki Krogerus 
5912cb78eabSKefeng Wang 	if (device_property_read_bool(dev, "ri-override")) {
5921bd8edbaSHeikki Krogerus 		/* Always report Ring indicator as inactive */
5931bd8edbaSHeikki Krogerus 		data->msr_mask_off |= UART_MSR_RI;
5941bd8edbaSHeikki Krogerus 		data->msr_mask_off |= UART_MSR_TERI;
5951bd8edbaSHeikki Krogerus 	}
5961bd8edbaSHeikki Krogerus 
59723f5b3fdSHeikki Krogerus 	/* If there is separate baudclk, get the rate from it. */
59870a0d499SAndy Shevchenko 	data->clk = devm_clk_get_optional_enabled(dev, "baudclk");
599a8afc193SAndy Shevchenko 	if (data->clk == NULL)
60070a0d499SAndy Shevchenko 		data->clk = devm_clk_get_optional_enabled(dev, NULL);
601a8afc193SAndy Shevchenko 	if (IS_ERR(data->clk))
60265295ebaSUwe Kleine-König 		return dev_err_probe(dev, PTR_ERR(data->clk),
60365295ebaSUwe Kleine-König 				     "failed to get baudclk\n");
604a8afc193SAndy Shevchenko 
605cc816969SSerge Semin 	INIT_WORK(&data->clk_work, dw8250_clk_work_cb);
606cc816969SSerge Semin 	data->clk_notifier.notifier_call = dw8250_clk_notifier_cb;
607cc816969SSerge Semin 
608a8afc193SAndy Shevchenko 	if (data->clk)
60978d3da75SHeikki Krogerus 		p->uartclk = clk_get_rate(data->clk);
610e302cd93SEmilio López 
61123f5b3fdSHeikki Krogerus 	/* If no clock rate is defined, fail. */
61257f83e5dSAndy Shevchenko 	if (!p->uartclk)
61357f83e5dSAndy Shevchenko 		return dev_err_probe(dev, -EINVAL, "clock rate not defined\n");
61423f5b3fdSHeikki Krogerus 
61570a0d499SAndy Shevchenko 	data->pclk = devm_clk_get_optional_enabled(dev, "apb_pclk");
616295b0912SAndy Shevchenko 	if (IS_ERR(data->pclk))
617295b0912SAndy Shevchenko 		return PTR_ERR(data->pclk);
618a8afc193SAndy Shevchenko 
619*41424f5cSHal Feng 	data->rst = devm_reset_control_array_get_optional_exclusive(dev);
620295b0912SAndy Shevchenko 	if (IS_ERR(data->rst))
621295b0912SAndy Shevchenko 		return PTR_ERR(data->rst);
622295b0912SAndy Shevchenko 
6237fe090bfSChen-Yu Tsai 	reset_control_deassert(data->rst);
6247fe090bfSChen-Yu Tsai 
625295b0912SAndy Shevchenko 	err = devm_add_action_or_reset(dev, dw8250_reset_control_assert, data->rst);
626295b0912SAndy Shevchenko 	if (err)
627295b0912SAndy Shevchenko 		return err;
628295b0912SAndy Shevchenko 
6299e08fa50SHeikki Krogerus 	dw8250_quirks(p, data);
6309bef3d41SPaul Gortmaker 
631c73942e2SHeikki Krogerus 	/* If the Busy Functionality is not implemented, don't handle it */
632cdcea058SNoam Camus 	if (data->uart_16550_compatible)
633c73942e2SHeikki Krogerus 		p->handle_irq = NULL;
634c73942e2SHeikki Krogerus 
6354f042054SHeikki Krogerus 	if (!data->skip_autocfg)
6362338a75eSHeikki Krogerus 		dw8250_setup_port(p);
6374f042054SHeikki Krogerus 
6382559318cSHeikki Krogerus 	/* If we have a valid fifosize, try hooking up DMA */
6392559318cSHeikki Krogerus 	if (p->fifosize) {
6404d5675c3SAndy Shevchenko 		data->data.dma.rxconf.src_maxburst = p->fifosize / 4;
6414d5675c3SAndy Shevchenko 		data->data.dma.txconf.dst_maxburst = p->fifosize / 4;
6424d5675c3SAndy Shevchenko 		up->dma = &data->data.dma;
6432559318cSHeikki Krogerus 	}
6442559318cSHeikki Krogerus 
6454d5675c3SAndy Shevchenko 	data->data.line = serial8250_register_8250_port(up);
646295b0912SAndy Shevchenko 	if (data->data.line < 0)
647295b0912SAndy Shevchenko 		return data->data.line;
6489bef3d41SPaul Gortmaker 
64985985a3dSSerge Semin 	/*
65085985a3dSSerge Semin 	 * Some platforms may provide a reference clock shared between several
65185985a3dSSerge Semin 	 * devices. In this case any clock state change must be known to the
65285985a3dSSerge Semin 	 * UART port at least post factum.
65385985a3dSSerge Semin 	 */
65485985a3dSSerge Semin 	if (data->clk) {
65585985a3dSSerge Semin 		err = clk_notifier_register(data->clk, &data->clk_notifier);
65685985a3dSSerge Semin 		if (err)
65757f83e5dSAndy Shevchenko 			return dev_err_probe(dev, err, "Failed to set the clock notifier\n");
65885985a3dSSerge Semin 		queue_work(system_unbound_wq, &data->clk_work);
65985985a3dSSerge Semin 	}
66085985a3dSSerge Semin 
6619bef3d41SPaul Gortmaker 	platform_set_drvdata(pdev, data);
6629bef3d41SPaul Gortmaker 
6632cb78eabSKefeng Wang 	pm_runtime_set_active(dev);
6642cb78eabSKefeng Wang 	pm_runtime_enable(dev);
665ffc3ae6dSHeikki Krogerus 
6669bef3d41SPaul Gortmaker 	return 0;
6679bef3d41SPaul Gortmaker }
6689bef3d41SPaul Gortmaker 
dw8250_remove(struct platform_device * pdev)6697e1efdf8SUwe Kleine-König static void dw8250_remove(struct platform_device *pdev)
6709bef3d41SPaul Gortmaker {
6719bef3d41SPaul Gortmaker 	struct dw8250_data *data = platform_get_drvdata(pdev);
672a8571fdaSAndy Shevchenko 	struct device *dev = &pdev->dev;
6739bef3d41SPaul Gortmaker 
674a8571fdaSAndy Shevchenko 	pm_runtime_get_sync(dev);
675ffc3ae6dSHeikki Krogerus 
67685985a3dSSerge Semin 	if (data->clk) {
67785985a3dSSerge Semin 		clk_notifier_unregister(data->clk, &data->clk_notifier);
67885985a3dSSerge Semin 
67985985a3dSSerge Semin 		flush_work(&data->clk_work);
68085985a3dSSerge Semin 	}
68185985a3dSSerge Semin 
6824d5675c3SAndy Shevchenko 	serial8250_unregister_port(data->data.line);
6839bef3d41SPaul Gortmaker 
684a8571fdaSAndy Shevchenko 	pm_runtime_disable(dev);
685a8571fdaSAndy Shevchenko 	pm_runtime_put_noidle(dev);
6869bef3d41SPaul Gortmaker }
6879bef3d41SPaul Gortmaker 
dw8250_suspend(struct device * dev)688ffc3ae6dSHeikki Krogerus static int dw8250_suspend(struct device *dev)
689b61c5ed5SJames Hogan {
690ffc3ae6dSHeikki Krogerus 	struct dw8250_data *data = dev_get_drvdata(dev);
691b61c5ed5SJames Hogan 
6924d5675c3SAndy Shevchenko 	serial8250_suspend_port(data->data.line);
693b61c5ed5SJames Hogan 
694b61c5ed5SJames Hogan 	return 0;
695b61c5ed5SJames Hogan }
696b61c5ed5SJames Hogan 
dw8250_resume(struct device * dev)697ffc3ae6dSHeikki Krogerus static int dw8250_resume(struct device *dev)
698b61c5ed5SJames Hogan {
699ffc3ae6dSHeikki Krogerus 	struct dw8250_data *data = dev_get_drvdata(dev);
700b61c5ed5SJames Hogan 
7014d5675c3SAndy Shevchenko 	serial8250_resume_port(data->data.line);
702b61c5ed5SJames Hogan 
703b61c5ed5SJames Hogan 	return 0;
704b61c5ed5SJames Hogan }
705b61c5ed5SJames Hogan 
dw8250_runtime_suspend(struct device * dev)706ffc3ae6dSHeikki Krogerus static int dw8250_runtime_suspend(struct device *dev)
707ffc3ae6dSHeikki Krogerus {
708ffc3ae6dSHeikki Krogerus 	struct dw8250_data *data = dev_get_drvdata(dev);
709ffc3ae6dSHeikki Krogerus 
710ffc3ae6dSHeikki Krogerus 	clk_disable_unprepare(data->clk);
711ffc3ae6dSHeikki Krogerus 
7127d78cbefSHeiko Stübner 	clk_disable_unprepare(data->pclk);
7137d78cbefSHeiko Stübner 
714ffc3ae6dSHeikki Krogerus 	return 0;
715ffc3ae6dSHeikki Krogerus }
716ffc3ae6dSHeikki Krogerus 
dw8250_runtime_resume(struct device * dev)717ffc3ae6dSHeikki Krogerus static int dw8250_runtime_resume(struct device *dev)
718ffc3ae6dSHeikki Krogerus {
719ffc3ae6dSHeikki Krogerus 	struct dw8250_data *data = dev_get_drvdata(dev);
720ffc3ae6dSHeikki Krogerus 
7217d78cbefSHeiko Stübner 	clk_prepare_enable(data->pclk);
7227d78cbefSHeiko Stübner 
723ffc3ae6dSHeikki Krogerus 	clk_prepare_enable(data->clk);
724ffc3ae6dSHeikki Krogerus 
725ffc3ae6dSHeikki Krogerus 	return 0;
726ffc3ae6dSHeikki Krogerus }
727ffc3ae6dSHeikki Krogerus 
728ffc3ae6dSHeikki Krogerus static const struct dev_pm_ops dw8250_pm_ops = {
729808313bcSAndy Shevchenko 	SYSTEM_SLEEP_PM_OPS(dw8250_suspend, dw8250_resume)
730808313bcSAndy Shevchenko 	RUNTIME_PM_OPS(dw8250_runtime_suspend, dw8250_runtime_resume, NULL)
731ffc3ae6dSHeikki Krogerus };
732ffc3ae6dSHeikki Krogerus 
7334a218b27SEmil Renner Berthing static const struct dw8250_platform_data dw8250_dw_apb = {
734ffd38144SMiquel Raynal 	.usr_reg = DW_UART_USR,
7354a218b27SEmil Renner Berthing };
7364a218b27SEmil Renner Berthing 
7374a218b27SEmil Renner Berthing static const struct dw8250_platform_data dw8250_octeon_3860_data = {
738ffd38144SMiquel Raynal 	.usr_reg = OCTEON_UART_USR,
7394a218b27SEmil Renner Berthing 	.quirks = DW_UART_QUIRK_OCTEON,
7404a218b27SEmil Renner Berthing };
7414a218b27SEmil Renner Berthing 
7424a218b27SEmil Renner Berthing static const struct dw8250_platform_data dw8250_armada_38x_data = {
743ffd38144SMiquel Raynal 	.usr_reg = DW_UART_USR,
7444a218b27SEmil Renner Berthing 	.quirks = DW_UART_QUIRK_ARMADA_38X,
7454a218b27SEmil Renner Berthing };
7464a218b27SEmil Renner Berthing 
7474a218b27SEmil Renner Berthing static const struct dw8250_platform_data dw8250_renesas_rzn1_data = {
748ffd38144SMiquel Raynal 	.usr_reg = DW_UART_USR,
74987d80bfbSAndy Shevchenko 	.cpr_value = 0x00012f32,
75087d80bfbSAndy Shevchenko 	.quirks = DW_UART_QUIRK_CPR_VALUE | DW_UART_QUIRK_IS_DMA_FC,
7514a218b27SEmil Renner Berthing };
7524a218b27SEmil Renner Berthing 
7534a218b27SEmil Renner Berthing static const struct dw8250_platform_data dw8250_starfive_jh7100_data = {
754ffd38144SMiquel Raynal 	.usr_reg = DW_UART_USR,
7554a218b27SEmil Renner Berthing 	.quirks = DW_UART_QUIRK_SKIP_SET_RATE,
7564a218b27SEmil Renner Berthing };
7574a218b27SEmil Renner Berthing 
758a7260c8cSHeikki Krogerus static const struct of_device_id dw8250_of_match[] = {
7594a218b27SEmil Renner Berthing 	{ .compatible = "snps,dw-apb-uart", .data = &dw8250_dw_apb },
7604a218b27SEmil Renner Berthing 	{ .compatible = "cavium,octeon-3860-uart", .data = &dw8250_octeon_3860_data },
7614a218b27SEmil Renner Berthing 	{ .compatible = "marvell,armada-38x-uart", .data = &dw8250_armada_38x_data },
7624a218b27SEmil Renner Berthing 	{ .compatible = "renesas,rzn1-uart", .data = &dw8250_renesas_rzn1_data },
7634a218b27SEmil Renner Berthing 	{ .compatible = "starfive,jh7100-uart", .data = &dw8250_starfive_jh7100_data },
7649bef3d41SPaul Gortmaker 	{ /* Sentinel */ }
7659bef3d41SPaul Gortmaker };
766a7260c8cSHeikki Krogerus MODULE_DEVICE_TABLE(of, dw8250_of_match);
7679bef3d41SPaul Gortmaker 
768173b097dSAndy Shevchenko static const struct dw8250_platform_data dw8250_apmc0d08 = {
769173b097dSAndy Shevchenko 	.usr_reg = DW_UART_USR,
770173b097dSAndy Shevchenko 	.quirks = DW_UART_QUIRK_APMC0D08,
771173b097dSAndy Shevchenko };
772173b097dSAndy Shevchenko 
7736a7320c4SHeikki Krogerus static const struct acpi_device_id dw8250_acpi_match[] = {
774cd16044dSMarcin Wojtas 	{ "80860F0A", (kernel_ulong_t)&dw8250_dw_apb },
775cd16044dSMarcin Wojtas 	{ "8086228A", (kernel_ulong_t)&dw8250_dw_apb },
776cd16044dSMarcin Wojtas 	{ "AMD0020", (kernel_ulong_t)&dw8250_dw_apb },
777cd16044dSMarcin Wojtas 	{ "AMDI0020", (kernel_ulong_t)&dw8250_dw_apb },
778cd16044dSMarcin Wojtas 	{ "AMDI0022", (kernel_ulong_t)&dw8250_dw_apb },
779173b097dSAndy Shevchenko 	{ "APMC0D08", (kernel_ulong_t)&dw8250_apmc0d08 },
780cd16044dSMarcin Wojtas 	{ "BRCM2032", (kernel_ulong_t)&dw8250_dw_apb },
781cd16044dSMarcin Wojtas 	{ "HISI0031", (kernel_ulong_t)&dw8250_dw_apb },
782cd16044dSMarcin Wojtas 	{ "INT33C4", (kernel_ulong_t)&dw8250_dw_apb },
783cd16044dSMarcin Wojtas 	{ "INT33C5", (kernel_ulong_t)&dw8250_dw_apb },
784cd16044dSMarcin Wojtas 	{ "INT3434", (kernel_ulong_t)&dw8250_dw_apb },
785cd16044dSMarcin Wojtas 	{ "INT3435", (kernel_ulong_t)&dw8250_dw_apb },
786e92fad02SAndy Shevchenko 	{ "INTC10EE", (kernel_ulong_t)&dw8250_dw_apb },
7876a7320c4SHeikki Krogerus 	{ },
7886a7320c4SHeikki Krogerus };
7896a7320c4SHeikki Krogerus MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match);
7906a7320c4SHeikki Krogerus 
7919bef3d41SPaul Gortmaker static struct platform_driver dw8250_platform_driver = {
7929bef3d41SPaul Gortmaker 	.driver = {
7939bef3d41SPaul Gortmaker 		.name		= "dw-apb-uart",
794808313bcSAndy Shevchenko 		.pm		= pm_ptr(&dw8250_pm_ops),
795a7260c8cSHeikki Krogerus 		.of_match_table	= dw8250_of_match,
796ebabb77aSAndy Shevchenko 		.acpi_match_table = dw8250_acpi_match,
7979bef3d41SPaul Gortmaker 	},
7989bef3d41SPaul Gortmaker 	.probe			= dw8250_probe,
7997e1efdf8SUwe Kleine-König 	.remove_new		= dw8250_remove,
8009bef3d41SPaul Gortmaker };
8019bef3d41SPaul Gortmaker 
8029bef3d41SPaul Gortmaker module_platform_driver(dw8250_platform_driver);
8039bef3d41SPaul Gortmaker 
8049bef3d41SPaul Gortmaker MODULE_AUTHOR("Jamie Iles");
8059bef3d41SPaul Gortmaker MODULE_LICENSE("GPL");
8069bef3d41SPaul Gortmaker MODULE_DESCRIPTION("Synopsys DesignWare 8250 serial port driver");
807f3ac3fc2SMika Westerberg MODULE_ALIAS("platform:dw-apb-uart");
808