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