Software APIs
dt_uart.c
Go to the documentation of this file.
1// Copyright lowRISC contributors (OpenTitan project).
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4//
5// Device table API auto-generated by `dtgen`
6
7/**
8 * @file
9 * @brief Device Tables (DT) for IP uart and top englishbreakfast.
10 */
11
12#include "hw/top/dt/dt_uart.h"
13
14
15
16/**
17 * Description of instances.
18 */
19typedef struct dt_desc_uart {
20 dt_instance_id_t inst_id; /**< Instance ID */
21 uint32_t reg_addr[kDtUartRegBlockCount]; /**< Base address of each register block */
22 uint32_t mem_addr[kDtUartMemoryCount]; /**< Base address of each memory */
23 uint32_t mem_size[kDtUartMemoryCount]; /**< Size in bytes of each memory */
24 /**
25 * PLIC ID of the first IRQ of this instance
26 *
27 * This can be `kDtPlicIrqIdNone` if the block is not connected to the PLIC.
28 */
30 dt_clock_t clock[kDtUartClockCount]; /**< Clock signal connected to each clock port */
31 dt_reset_t reset[kDtUartResetCount]; /**< Reset signal connected to each reset port */
32 dt_periph_io_t periph_io[kDtUartPeriphIoCount]; /**< Description of each peripheral I/O */
34
35
36
37
38static const dt_desc_uart_t uart_desc[kDtUartCount] = {
39 [kDtUart0] = {
40 .inst_id = kDtInstanceIdUart0,
41 .reg_addr = {
42 [kDtUartRegBlockCore] = 0x40000000,
43 },
44 .mem_addr = {
45 },
46 .mem_size = {
47 },
49 .clock = {
51 },
52 .reset = {
54 },
55 .periph_io = {
56 [kDtUartPeriphIoRx] = {
57 .__internal = {
58 .type = kDtPeriphIoTypeMio,
59 .dir = kDtPeriphIoDirIn,
60 .periph_input_or_direct_pad = kTopEnglishbreakfastPinmuxPeripheralInUart0Rx,
61 .outsel_or_dt_pad = 0,
62 },
63 },
64 [kDtUartPeriphIoTx] = {
65 .__internal = {
66 .type = kDtPeriphIoTypeMio,
67 .dir = kDtPeriphIoDirOut,
68 .periph_input_or_direct_pad = 0,
70 },
71 },
72 },
73 },
74 [kDtUart1] = {
75 .inst_id = kDtInstanceIdUart1,
76 .reg_addr = {
77 [kDtUartRegBlockCore] = 0x40010000,
78 },
79 .mem_addr = {
80 },
81 .mem_size = {
82 },
84 .clock = {
86 },
87 .reset = {
89 },
90 .periph_io = {
91 [kDtUartPeriphIoRx] = {
92 .__internal = {
93 .type = kDtPeriphIoTypeMio,
94 .dir = kDtPeriphIoDirIn,
95 .periph_input_or_direct_pad = kTopEnglishbreakfastPinmuxPeripheralInUart1Rx,
96 .outsel_or_dt_pad = 0,
97 },
98 },
99 [kDtUartPeriphIoTx] = {
100 .__internal = {
101 .type = kDtPeriphIoTypeMio,
102 .dir = kDtPeriphIoDirOut,
103 .periph_input_or_direct_pad = 0,
104 .outsel_or_dt_pad = kTopEnglishbreakfastPinmuxOutselUart1Tx,
105 },
106 },
107 },
108 },
109};
110
111/**
112 * Return a pointer to the `dt_uart_desc_t` structure of the requested
113 * `dt` if it's a valid index. Otherwise, this macro will `return` (i.e. exit
114 * the function) with the provided default value.
115 */
116#define TRY_GET_DT(dt, default) ({ if ((dt) < (dt_uart_t)0 || (dt) >= kDtUartCount) return (default); &uart_desc[dt]; })
117
119 if (inst_id >= kDtInstanceIdUart0 && inst_id <= kDtInstanceIdUart1) {
120 return (dt_uart_t)(inst_id - kDtInstanceIdUart0);
121 }
122 return (dt_uart_t)0;
123}
124
129
131 dt_uart_t dt,
132 dt_uart_reg_block_t reg_block) {
133 // Return a recognizable address in case of wrong argument.
134 return TRY_GET_DT(dt, 0xdeadbeef)->reg_addr[reg_block];
135}
136
138 dt_uart_t dt,
139 dt_uart_memory_t mem) {
140 // Return a recognizable address in case of wrong argument.
141 return TRY_GET_DT(dt, 0xdeadbeef)->mem_addr[mem];
142}
143
145 dt_uart_t dt,
146 dt_uart_memory_t mem) {
147 // Return an empty size in case of wrong argument.
148 return TRY_GET_DT(dt, 0)->mem_size[mem];
149}
150
152 dt_uart_t dt,
153 dt_uart_irq_t irq) {
154 dt_plic_irq_id_t first_irq = TRY_GET_DT(dt, kDtPlicIrqIdNone)->first_irq;
155 if (first_irq == kDtPlicIrqIdNone) {
156 return kDtPlicIrqIdNone;
157 }
158 return (dt_plic_irq_id_t)((uint32_t)first_irq + (uint32_t)irq);
159}
160
162 dt_uart_t dt,
163 dt_plic_irq_id_t irq) {
164 dt_uart_irq_t count = kDtUartIrqCount;
165 dt_plic_irq_id_t first_irq = TRY_GET_DT(dt, count)->first_irq;
166 if (first_irq == kDtPlicIrqIdNone) {
167 return count;
168 }
169 if (irq < first_irq || irq >= first_irq + (dt_plic_irq_id_t)count) {
170 return count;
171 }
172 return (dt_uart_irq_t)(irq - first_irq);
173}
174
175
176
178 dt_uart_t dt,
180 // Return a harmless value in case of wrong argument.
181 return TRY_GET_DT(dt, kDtPeriphIoConstantHighZ)->periph_io[sig];
182}
183
185 dt_uart_t dt,
186 dt_uart_clock_t clk) {
187 // Return the first clock in case of invalid argument.
188 return TRY_GET_DT(dt, (dt_clock_t)0)->clock[clk];
189}
190
192 dt_uart_t dt,
193 dt_uart_reset_t rst) {
194 const dt_uart_reset_t count = kDtUartResetCount;
195 if (rst >= count) {
196 return kDtResetUnknown;
197 }
198 return TRY_GET_DT(dt, kDtResetUnknown)->reset[rst];
199}
200
201