Skip to content

Commit 601f2fd

Browse files
ndrs-pstcfriedt
authored andcommitted
drivers: serial: pl011: reduce device's base address accesses
In several functions, the UART registers are accessed multiple times through the `get_uart(dev)` inline function. This results in repeated dereferencing of the device's base address. This commit caches the UART register struct pointer in a local variable `uart` at the beginning of each relevant function. For registers where repeated access is not needed, the value is read once into a temporary variable. Modifications, if any, are applied to the temporary copy, and the result is written back once. Signed-off-by: Pisit Sawangvonganan <[email protected]>
1 parent 19dc74b commit 601f2fd

File tree

1 file changed

+61
-37
lines changed

1 file changed

+61
-37
lines changed

drivers/serial/uart_pl011.c

Lines changed: 61 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -133,16 +133,22 @@ static void pl011_disable_fifo(const struct device *dev)
133133

134134
static void pl011_set_flow_control(const struct device *dev, bool rts, bool cts)
135135
{
136+
volatile struct pl011_regs *uart = get_uart(dev);
137+
uint32_t cr = uart->cr;
138+
136139
if (rts) {
137-
get_uart(dev)->cr |= PL011_CR_RTSEn;
140+
cr |= PL011_CR_RTSEn;
138141
} else {
139-
get_uart(dev)->cr &= ~PL011_CR_RTSEn;
142+
cr &= ~PL011_CR_RTSEn;
140143
}
144+
141145
if (cts) {
142-
get_uart(dev)->cr |= PL011_CR_CTSEn;
146+
cr |= PL011_CR_CTSEn;
143147
} else {
144-
get_uart(dev)->cr &= ~PL011_CR_CTSEn;
148+
cr &= ~PL011_CR_CTSEn;
145149
}
150+
151+
uart->cr = cr;
146152
}
147153

148154
static int pl011_set_baudrate(const struct device *dev,
@@ -151,6 +157,7 @@ static int pl011_set_baudrate(const struct device *dev,
151157
/* Avoiding float calculations, bauddiv is left shifted by 6 */
152158
uint64_t bauddiv = (((uint64_t)clk) << PL011_FBRD_WIDTH)
153159
/ (baudrate * 16U);
160+
volatile struct pl011_regs *uart = get_uart(dev);
154161

155162
/* Valid bauddiv value
156163
* uart_clk (min) >= 16 x baud_rate (max)
@@ -161,73 +168,80 @@ static int pl011_set_baudrate(const struct device *dev,
161168
return -EINVAL;
162169
}
163170

164-
get_uart(dev)->ibrd = bauddiv >> PL011_FBRD_WIDTH;
165-
get_uart(dev)->fbrd = bauddiv & ((1u << PL011_FBRD_WIDTH) - 1u);
171+
uart->ibrd = bauddiv >> PL011_FBRD_WIDTH;
172+
uart->fbrd = bauddiv & ((1u << PL011_FBRD_WIDTH) - 1u);
166173

167174
barrier_dmem_fence_full();
168175

169176
/* In order to internally update the contents of ibrd or fbrd, a
170177
* lcr_h write must always be performed at the end
171178
* ARM DDI 0183F, Pg 3-13
172179
*/
173-
get_uart(dev)->lcr_h = get_uart(dev)->lcr_h;
180+
uart->lcr_h = uart->lcr_h;
174181

175182
return 0;
176183
}
177184

178185
static bool pl011_is_readable(const struct device *dev)
179186
{
180187
struct pl011_data *data = dev->data;
188+
volatile struct pl011_regs *uart = get_uart(dev);
189+
uint32_t cr = uart->cr;
181190

182191
if (!data->sbsa &&
183-
(!(get_uart(dev)->cr & PL011_CR_UARTEN) || !(get_uart(dev)->cr & PL011_CR_RXE))) {
192+
(!(cr & PL011_CR_UARTEN) || !(cr & PL011_CR_RXE))) {
184193
return false;
185194
}
186195

187-
return (get_uart(dev)->fr & PL011_FR_RXFE) == 0U;
196+
return (uart->fr & PL011_FR_RXFE) == 0U;
188197
}
189198

190199
static int pl011_poll_in(const struct device *dev, unsigned char *c)
191200
{
201+
volatile struct pl011_regs *uart = get_uart(dev);
202+
192203
if (!pl011_is_readable(dev)) {
193204
return -1;
194205
}
195206

196207
/* got a character */
197-
*c = (unsigned char)get_uart(dev)->dr;
208+
*c = (unsigned char)uart->dr;
198209

199-
return get_uart(dev)->rsr & PL011_RSR_ERROR_MASK;
210+
return uart->rsr & PL011_RSR_ERROR_MASK;
200211
}
201212

202213
static void pl011_poll_out(const struct device *dev,
203214
unsigned char c)
204215
{
216+
volatile struct pl011_regs *uart = get_uart(dev);
217+
205218
/* Wait for space in FIFO */
206-
while (get_uart(dev)->fr & PL011_FR_TXFF) {
219+
while (uart->fr & PL011_FR_TXFF) {
207220
; /* Wait */
208221
}
209222

210223
/* Send a character */
211-
get_uart(dev)->dr = (uint32_t)c;
224+
uart->dr = (uint32_t)c;
212225
}
213226

214227
static int pl011_err_check(const struct device *dev)
215228
{
229+
uint32_t rsr = get_uart(dev)->rsr;
216230
int errors = 0;
217231

218-
if (get_uart(dev)->rsr & PL011_RSR_ECR_OE) {
232+
if (rsr & PL011_RSR_ECR_OE) {
219233
errors |= UART_ERROR_OVERRUN;
220234
}
221235

222-
if (get_uart(dev)->rsr & PL011_RSR_ECR_BE) {
236+
if (rsr & PL011_RSR_ECR_BE) {
223237
errors |= UART_BREAK;
224238
}
225239

226-
if (get_uart(dev)->rsr & PL011_RSR_ECR_PE) {
240+
if (rsr & PL011_RSR_ECR_PE) {
227241
errors |= UART_ERROR_PARITY;
228242
}
229243

230-
if (get_uart(dev)->rsr & PL011_RSR_ECR_FE) {
244+
if (rsr & PL011_RSR_ECR_FE) {
231245
errors |= UART_ERROR_FRAMING;
232246
}
233247

@@ -240,6 +254,7 @@ static int pl011_runtime_configure_internal(const struct device *dev,
240254
{
241255
const struct pl011_config *config = dev->config;
242256
struct pl011_data *data = dev->data;
257+
volatile struct pl011_regs *uart = get_uart(dev);
243258
uint32_t lcrh;
244259
int ret = -ENOTSUP;
245260

@@ -252,7 +267,7 @@ static int pl011_runtime_configure_internal(const struct device *dev,
252267
pl011_disable_fifo(dev);
253268
}
254269

255-
lcrh = get_uart(dev)->lcr_h & ~(PL011_LCRH_FORMAT_MASK | PL011_LCRH_STP2);
270+
lcrh = uart->lcr_h & ~(PL011_LCRH_FORMAT_MASK | PL011_LCRH_STP2);
256271

257272
switch (cfg->parity) {
258273
case UART_CFG_PARITY_NONE:
@@ -314,7 +329,7 @@ static int pl011_runtime_configure_internal(const struct device *dev,
314329
}
315330

316331
/* Update settings */
317-
get_uart(dev)->lcr_h = lcrh;
332+
uart->lcr_h = lcrh;
318333

319334
memcpy(&data->uart_cfg, cfg, sizeof(data->uart_cfg));
320335

@@ -353,21 +368,23 @@ static int pl011_runtime_config_get(const struct device *dev,
353368
static int pl011_fifo_fill(const struct device *dev,
354369
const uint8_t *tx_data, int len)
355370
{
371+
volatile struct pl011_regs *uart = get_uart(dev);
356372
int num_tx = 0U;
357373

358-
while (!(get_uart(dev)->fr & PL011_FR_TXFF) && (len - num_tx > 0)) {
359-
get_uart(dev)->dr = tx_data[num_tx++];
374+
while (!(uart->fr & PL011_FR_TXFF) && (len - num_tx > 0)) {
375+
uart->dr = tx_data[num_tx++];
360376
}
361377
return num_tx;
362378
}
363379

364380
static int pl011_fifo_read(const struct device *dev,
365381
uint8_t *rx_data, const int len)
366382
{
383+
volatile struct pl011_regs *uart = get_uart(dev);
367384
int num_rx = 0U;
368385

369-
while ((len - num_rx > 0) && !(get_uart(dev)->fr & PL011_FR_RXFE)) {
370-
rx_data[num_rx++] = get_uart(dev)->dr;
386+
while ((len - num_rx > 0) && !(uart->fr & PL011_FR_RXFE)) {
387+
rx_data[num_rx++] = uart->dr;
371388
}
372389

373390
return num_rx;
@@ -376,8 +393,9 @@ static int pl011_fifo_read(const struct device *dev,
376393
static void pl011_irq_tx_enable(const struct device *dev)
377394
{
378395
struct pl011_data *data = dev->data;
396+
volatile struct pl011_regs *uart = get_uart(dev);
379397

380-
get_uart(dev)->imsc |= PL011_IMSC_TXIM;
398+
uart->imsc |= PL011_IMSC_TXIM;
381399
if (!data->sw_call_txdrdy) {
382400
return;
383401
}
@@ -405,7 +423,7 @@ static void pl011_irq_tx_enable(const struct device *dev)
405423
* FIFO threshold may never be reached, and the hardware TX interrupt
406424
* will never trigger.
407425
*/
408-
while (get_uart(dev)->imsc & PL011_IMSC_TXIM) {
426+
while (uart->imsc & PL011_IMSC_TXIM) {
409427
K_SPINLOCK(&data->irq_cb_lock) {
410428
data->irq_cb(dev, data->irq_cb_data);
411429
}
@@ -429,14 +447,15 @@ static int pl011_irq_tx_complete(const struct device *dev)
429447
static int pl011_irq_tx_ready(const struct device *dev)
430448
{
431449
struct pl011_data *data = dev->data;
450+
volatile struct pl011_regs *uart = get_uart(dev);
432451

433-
if (!data->sbsa && !(get_uart(dev)->cr & PL011_CR_TXE)) {
452+
if (!data->sbsa && !(uart->cr & PL011_CR_TXE)) {
434453
return false;
435454
}
436455

437-
return ((get_uart(dev)->imsc & PL011_IMSC_TXIM) &&
456+
return ((uart->imsc & PL011_IMSC_TXIM) &&
438457
/* Check for TX interrupt status is set or TX FIFO is empty. */
439-
(get_uart(dev)->ris & PL011_RIS_TXRIS || get_uart(dev)->fr & PL011_FR_TXFE));
458+
(uart->ris & PL011_RIS_TXRIS || uart->fr & PL011_FR_TXFE));
440459
}
441460

442461
static void pl011_irq_rx_enable(const struct device *dev)
@@ -451,14 +470,15 @@ static void pl011_irq_rx_disable(const struct device *dev)
451470

452471
static int pl011_irq_rx_ready(const struct device *dev)
453472
{
473+
volatile struct pl011_regs *uart = get_uart(dev);
454474
struct pl011_data *data = dev->data;
455475

456-
if (!data->sbsa && !(get_uart(dev)->cr & PL011_CR_RXE)) {
476+
if (!data->sbsa && !(uart->cr & PL011_CR_RXE)) {
457477
return false;
458478
}
459479

460-
return ((get_uart(dev)->imsc & PL011_IMSC_RXIM) &&
461-
(!(get_uart(dev)->fr & PL011_FR_RXFE)));
480+
return ((uart->imsc & PL011_IMSC_RXIM) &&
481+
(!(uart->fr & PL011_FR_RXFE)));
462482
}
463483

464484
static void pl011_irq_err_enable(const struct device *dev)
@@ -523,10 +543,14 @@ static int pl011_init(const struct device *dev)
523543
{
524544
const struct pl011_config *config = dev->config;
525545
struct pl011_data *data = dev->data;
546+
volatile struct pl011_regs *uart;
526547
int ret;
527548

528549
DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE);
529550

551+
/* Must be placed after DEVICE_MMIO_MAP */
552+
uart = get_uart(dev);
553+
530554
#if defined(CONFIG_RESET)
531555
if (config->reset.dev) {
532556
ret = reset_line_toggle_dt(&config->reset);
@@ -575,7 +599,7 @@ static int pl011_init(const struct device *dev)
575599
pl011_runtime_configure_internal(dev, &data->uart_cfg, false);
576600

577601
/* Setting transmit and receive interrupt FIFO level */
578-
get_uart(dev)->ifls = FIELD_PREP(PL011_IFLS_TXIFLSEL_M, TXIFLSEL_1_8_FULL)
602+
uart->ifls = FIELD_PREP(PL011_IFLS_TXIFLSEL_M, TXIFLSEL_1_8_FULL)
579603
| FIELD_PREP(PL011_IFLS_RXIFLSEL_M, RXIFLSEL_1_2_FULL);
580604

581605
/* Enabling the FIFOs */
@@ -584,14 +608,14 @@ static int pl011_init(const struct device *dev)
584608
}
585609
}
586610
/* initialize all IRQs as masked */
587-
get_uart(dev)->imsc = 0U;
588-
get_uart(dev)->icr = PL011_IMSC_MASK_ALL;
611+
uart->imsc = 0U;
612+
uart->icr = PL011_IMSC_MASK_ALL;
589613

590614
if (!data->sbsa) {
591-
get_uart(dev)->dmacr = 0U;
615+
uart->dmacr = 0U;
592616
barrier_isync_fence_full();
593-
get_uart(dev)->cr &= ~PL011_CR_SIREN;
594-
get_uart(dev)->cr |= PL011_CR_RXE | PL011_CR_TXE;
617+
uart->cr &= ~PL011_CR_SIREN;
618+
uart->cr |= PL011_CR_RXE | PL011_CR_TXE;
595619
barrier_isync_fence_full();
596620
}
597621
#ifdef CONFIG_UART_INTERRUPT_DRIVEN

0 commit comments

Comments
 (0)