Skip to content

Commit 3a0ab62

Browse files
Uwe Kleine-Königgregkh
authored andcommitted
serial: imx: implement shadow registers for UCRx and UFCR
This reduces the amount of read accesses to the register space by shadowing the values for five registers that only change on writing them. There is a single bit in UCR2 that might change without being written to it, this is handled accordingly. Signed-off-by: Uwe Kleine-König <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 27c8442 commit 3a0ab62

File tree

1 file changed

+59
-1
lines changed

1 file changed

+59
-1
lines changed

drivers/tty/serial/imx.c

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,13 @@ struct imx_port {
204204

205205
struct mctrl_gpios *gpios;
206206

207+
/* shadow registers */
208+
unsigned int ucr1;
209+
unsigned int ucr2;
210+
unsigned int ucr3;
211+
unsigned int ucr4;
212+
unsigned int ufcr;
213+
207214
/* DMA fields */
208215
unsigned int dma_is_enabled:1;
209216
unsigned int dma_is_rxing:1;
@@ -275,12 +282,56 @@ MODULE_DEVICE_TABLE(of, imx_uart_dt_ids);
275282

276283
static void imx_uart_writel(struct imx_port *sport, u32 val, u32 offset)
277284
{
285+
switch (offset) {
286+
case UCR1:
287+
sport->ucr1 = val;
288+
break;
289+
case UCR2:
290+
sport->ucr2 = val;
291+
break;
292+
case UCR3:
293+
sport->ucr3 = val;
294+
break;
295+
case UCR4:
296+
sport->ucr4 = val;
297+
break;
298+
case UFCR:
299+
sport->ufcr = val;
300+
break;
301+
default:
302+
break;
303+
}
278304
writel(val, sport->port.membase + offset);
279305
}
280306

281307
static u32 imx_uart_readl(struct imx_port *sport, u32 offset)
282308
{
283-
return readl(sport->port.membase + offset);
309+
switch (offset) {
310+
case UCR1:
311+
return sport->ucr1;
312+
break;
313+
case UCR2:
314+
/*
315+
* UCR2_SRST is the only bit in the cached registers that might
316+
* differ from the value that was last written. As it only
317+
* clears after being set, reread conditionally.
318+
*/
319+
if (sport->ucr2 & UCR2_SRST)
320+
sport->ucr2 = readl(sport->port.membase + offset);
321+
return sport->ucr2;
322+
break;
323+
case UCR3:
324+
return sport->ucr3;
325+
break;
326+
case UCR4:
327+
return sport->ucr4;
328+
break;
329+
case UFCR:
330+
return sport->ufcr;
331+
break;
332+
default:
333+
return readl(sport->port.membase + offset);
334+
}
284335
}
285336

286337
static inline unsigned uts_reg(struct imx_port *sport)
@@ -2136,6 +2187,13 @@ static int serial_imx_probe(struct platform_device *pdev)
21362187
return ret;
21372188
}
21382189

2190+
/* initialize shadow register values */
2191+
sport->ucr1 = readl(sport->port.membase + UCR1);
2192+
sport->ucr2 = readl(sport->port.membase + UCR2);
2193+
sport->ucr3 = readl(sport->port.membase + UCR3);
2194+
sport->ucr4 = readl(sport->port.membase + UCR4);
2195+
sport->ufcr = readl(sport->port.membase + UFCR);
2196+
21392197
uart_get_rs485_mode(&pdev->dev, &sport->port.rs485);
21402198

21412199
if (sport->port.rs485.flags & SER_RS485_ENABLED &&

0 commit comments

Comments
 (0)