aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUwe Kleine-König <u.kleine-koenig@pengutronix.de>2018-03-02 05:07:20 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-03-09 13:21:01 -0500
commit3a0ab62f43de5c6ec55fb9d6721168602008142a (patch)
treec57e3c5448196442e1b6c61e1728f71505183126
parent27c844261b87f85f23784e78170883092428e5a1 (diff)
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 <u.kleine-koenig@pengutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/tty/serial/imx.c60
1 files changed, 59 insertions, 1 deletions
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 659a949bed8a..57891d21f20d 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -204,6 +204,13 @@ struct imx_port {
204 204
205 struct mctrl_gpios *gpios; 205 struct mctrl_gpios *gpios;
206 206
207 /* shadow registers */
208 unsigned int ucr1;
209 unsigned int ucr2;
210 unsigned int ucr3;
211 unsigned int ucr4;
212 unsigned int ufcr;
213
207 /* DMA fields */ 214 /* DMA fields */
208 unsigned int dma_is_enabled:1; 215 unsigned int dma_is_enabled:1;
209 unsigned int dma_is_rxing:1; 216 unsigned int dma_is_rxing:1;
@@ -275,12 +282,56 @@ MODULE_DEVICE_TABLE(of, imx_uart_dt_ids);
275 282
276static void imx_uart_writel(struct imx_port *sport, u32 val, u32 offset) 283static void imx_uart_writel(struct imx_port *sport, u32 val, u32 offset)
277{ 284{
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 }
278 writel(val, sport->port.membase + offset); 304 writel(val, sport->port.membase + offset);
279} 305}
280 306
281static u32 imx_uart_readl(struct imx_port *sport, u32 offset) 307static u32 imx_uart_readl(struct imx_port *sport, u32 offset)
282{ 308{
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 }
284} 335}
285 336
286static inline unsigned uts_reg(struct imx_port *sport) 337static inline unsigned uts_reg(struct imx_port *sport)
@@ -2136,6 +2187,13 @@ static int serial_imx_probe(struct platform_device *pdev)
2136 return ret; 2187 return ret;
2137 } 2188 }
2138 2189
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
2139 uart_get_rs485_mode(&pdev->dev, &sport->port.rs485); 2197 uart_get_rs485_mode(&pdev->dev, &sport->port.rs485);
2140 2198
2141 if (sport->port.rs485.flags & SER_RS485_ENABLED && 2199 if (sport->port.rs485.flags & SER_RS485_ENABLED &&