1 /*
2 * Copyright (c) 2020 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/ztest.h>
8 #include <zephyr/device.h>
9
10 #define DT_DRV_COMPAT fakedriver
11
12 /*
13 * Driver with a single MMIO region to manage
14 */
15
16 struct foo_single_dev_data {
17 DEVICE_MMIO_RAM;
18 int baz;
19 };
20
21 struct foo_single_dev_data foo0_data;
22
23 struct foo_single_config_info {
24 DEVICE_MMIO_ROM;
25 };
26
27 const struct foo_single_config_info foo0_config = {
28 DEVICE_MMIO_ROM_INIT(DT_DRV_INST(0)),
29 };
30
foo_single_init(const struct device * dev)31 int foo_single_init(const struct device *dev)
32 {
33 DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE);
34
35 return 0;
36 }
37
38 /* fake API pointer, we don't use it at all for this suite */
39 DEVICE_DEFINE(foo0, "foo0", foo_single_init, NULL,
40 &foo0_data, &foo0_config,
41 POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
42 (void *)0xDEADBEEF);
43
44 /**
45 * @brief Test DEVICE_MMIO_* macros
46 *
47 * We show that we can make mapping calls and that the address returned by
48 * DEVICE_MMIO_GET() is not NULL, indicating that the kernel mapped
49 * stuff somewhere.
50 *
51 * We also perform some checks depending on configuration:
52 * - If MMIO addresses are maintained in RAM, check that the ROM struct
53 * was populated correctly.
54 * - If MMIO addresses are maintained in ROM, check that the DTS info,
55 * the ROM region, and the result of DEVICE_MMIO_GET() all
56 * point to the same address. We show that no extra memory is used in
57 * dev_data.
58 *
59 * @ingroup kernel_device_tests
60 */
ZTEST(device,test_mmio_single)61 ZTEST(device, test_mmio_single)
62 {
63 const struct z_device_mmio_rom *rom;
64 const struct device *dev = device_get_binding("foo0");
65 mm_reg_t regs;
66
67 zassert_not_null(dev, "null foo0");
68
69 regs = DEVICE_MMIO_GET(dev);
70 rom = DEVICE_MMIO_ROM_PTR(dev);
71
72 /* A sign that something didn't get initialized, shouldn't ever
73 * be 0
74 */
75 zassert_not_equal(regs, 0, "NULL regs");
76
77 #ifdef DEVICE_MMIO_IS_IN_RAM
78 /* The config info should just contain the addr/size from DTS.
79 * The best we can check with 'regs' is that it's nonzero, as if
80 * an MMU is enabled, the kernel chooses the virtual address to
81 * place it at. We don't otherwise look at `regs`; other tests will
82 * prove that k_map() actually works.
83 */
84 zassert_equal(rom->phys_addr, DT_INST_REG_ADDR(0), "bad phys_addr");
85 zassert_equal(rom->size, DT_INST_REG_SIZE(0), "bad size");
86 #else
87 /* Config info contains base address, which should be the base
88 * address from DTS, and regs should have the same value.
89 * In this configuration dev_data has nothing mmio-related in it
90 */
91 zassert_equal(rom->addr, DT_INST_REG_ADDR(0), "bad addr");
92 zassert_equal(regs, rom->addr, "bad regs");
93 /* Just the baz member */
94 zassert_equal(sizeof(struct foo_single_dev_data), sizeof(int),
95 "too big foo_single_dev_data");
96 #endif
97 }
98
99 /*
100 * Driver with multiple MMIO regions to manage
101 */
102
103 struct foo_mult_dev_data {
104 int baz;
105
106 DEVICE_MMIO_NAMED_RAM(corge);
107 DEVICE_MMIO_NAMED_RAM(grault);
108 };
109
110 struct foo_mult_dev_data foo12_data;
111
112 struct foo_mult_config_info {
113 DEVICE_MMIO_NAMED_ROM(corge);
114 DEVICE_MMIO_NAMED_ROM(grault);
115 };
116
117 const struct foo_mult_config_info foo12_config = {
118 DEVICE_MMIO_NAMED_ROM_INIT(corge, DT_DRV_INST(1)),
119 DEVICE_MMIO_NAMED_ROM_INIT(grault, DT_DRV_INST(2))
120 };
121
122 #define DEV_DATA(dev) ((struct foo_mult_dev_data *)((dev)->data))
123 #define DEV_CFG(dev) ((struct foo_mult_config_info *)((dev)->config))
124
foo_mult_init(const struct device * dev)125 int foo_mult_init(const struct device *dev)
126 {
127 DEVICE_MMIO_NAMED_MAP(dev, corge, K_MEM_CACHE_NONE);
128 DEVICE_MMIO_NAMED_MAP(dev, grault, K_MEM_CACHE_NONE);
129
130 return 0;
131 }
132
133 DEVICE_DEFINE(foo12, "foo12", foo_mult_init, NULL,
134 &foo12_data, &foo12_config,
135 POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
136 (void *)0xDEADBEEF);
137
138 /**
139 * @brief Test DEVICE_MMIO_NAMED_* macros
140 *
141 * We show that we can make mapping calls and that the address returned by
142 * DEVICE_MMIO_NAMED_GET() is not NULL, indicating that the kernel mapped
143 * stuff somewhere.
144 *
145 * We show that this works for a device instance that has two named regions,
146 * 'corge' and 'grault' that respectively come from DTS instances 1 and 2.
147 *
148 * We also perform some checks depending on configuration:
149 * - If MMIO addresses are maintained in RAM, check that the ROM struct
150 * was populated correctly.
151 * - If MMIO addresses are maintained in ROM, check that the DTS info,
152 * the ROM region, and the result of DEVICE_MMIO_NAMED_GET() all
153 * point to the same address. We show that no extra memory is used in
154 * dev_data.
155 *
156 * @ingroup kernel_device_tests
157 */
ZTEST(device,test_mmio_multiple)158 ZTEST(device, test_mmio_multiple)
159 {
160 /* See comments for test_mmio_single */
161 const struct device *dev = device_get_binding("foo12");
162 mm_reg_t regs_corge, regs_grault;
163 const struct z_device_mmio_rom *rom_corge, *rom_grault;
164
165 zassert_not_null(dev, "null foo12");
166
167 regs_corge = DEVICE_MMIO_NAMED_GET(dev, corge);
168 regs_grault = DEVICE_MMIO_NAMED_GET(dev, grault);
169 rom_corge = DEVICE_MMIO_NAMED_ROM_PTR(dev, corge);
170 rom_grault = DEVICE_MMIO_NAMED_ROM_PTR(dev, grault);
171
172 zassert_not_equal(regs_corge, 0, "bad regs_corge");
173 zassert_not_equal(regs_grault, 0, "bad regs_grault");
174
175 #ifdef DEVICE_MMIO_IS_IN_RAM
176 zassert_equal(rom_corge->phys_addr, DT_INST_REG_ADDR(1),
177 "bad phys_addr (corge)");
178 zassert_equal(rom_corge->size, DT_INST_REG_SIZE(1),
179 "bad size (corge)");
180 zassert_equal(rom_grault->phys_addr, DT_INST_REG_ADDR(2),
181 "bad phys_addr (grault)");
182 zassert_equal(rom_grault->size, DT_INST_REG_SIZE(2),
183 "bad size (grault)");
184 #else
185 zassert_equal(rom_corge->addr, DT_INST_REG_ADDR(1),
186 "bad addr (corge)");
187 zassert_equal(regs_corge, rom_corge->addr, "bad regs (corge)");
188 zassert_equal(rom_grault->addr, DT_INST_REG_ADDR(2),
189 "bad addr (grault)");
190 zassert_equal(regs_grault, rom_grault->addr, "bad regs (grault)");
191 zassert_equal(sizeof(struct foo_mult_dev_data), sizeof(int),
192 "too big foo_mult_dev_data");
193 #endif
194 }
195
196 /*
197 * Not using driver model, toplevel definition
198 */
199 DEVICE_MMIO_TOPLEVEL(foo3, DT_DRV_INST(3));
200 DEVICE_MMIO_TOPLEVEL_STATIC(foo4, DT_DRV_INST(4));
201
202 /**
203 * @brief Test DEVICE_MMIO_TOPLEVEL_* macros
204 *
205 * We show that we can make mapping calls and that the address returned by
206 * DEVICE_MMIO_TOPLEVEL_GET() is not NULL, indicating that the kernel mapped
207 * stuff somewhere.
208 *
209 * We do this for two different MMIO toplevel instances; one declared
210 * statically and one not.
211 *
212 * We also perform some checks depending on configuration:
213 * - If MMIO addresses are maintained in RAM, check that the ROM struct
214 * was populated correctly.
215 * - If MMIO addresses are maintained in ROM, check that the DTS info,
216 * the ROM region, and the result of DEVICE_MMIO_TOPLEVEL_GET() all
217 * point to the same address
218 *
219 * @ingroup kernel_device_tests
220 */
ZTEST(device,test_mmio_toplevel)221 ZTEST(device, test_mmio_toplevel)
222 {
223 mm_reg_t regs_foo3, regs_foo4;
224 const struct z_device_mmio_rom *rom_foo3, *rom_foo4;
225
226 DEVICE_MMIO_TOPLEVEL_MAP(foo3, K_MEM_CACHE_NONE);
227 DEVICE_MMIO_TOPLEVEL_MAP(foo4, K_MEM_CACHE_NONE);
228
229 regs_foo3 = DEVICE_MMIO_TOPLEVEL_GET(foo3);
230 regs_foo4 = DEVICE_MMIO_TOPLEVEL_GET(foo4);
231 rom_foo3 = DEVICE_MMIO_TOPLEVEL_ROM_PTR(foo3);
232 rom_foo4 = DEVICE_MMIO_TOPLEVEL_ROM_PTR(foo4);
233
234 zassert_not_equal(regs_foo3, 0, "bad regs_corge");
235 zassert_not_equal(regs_foo4, 0, "bad regs_grault");
236
237 #ifdef DEVICE_MMIO_IS_IN_RAM
238 zassert_equal(rom_foo3->phys_addr, DT_INST_REG_ADDR(3),
239 "bad phys_addr (foo3)");
240 zassert_equal(rom_foo3->size, DT_INST_REG_SIZE(3),
241 "bad size (foo3)");
242 zassert_equal(rom_foo4->phys_addr, DT_INST_REG_ADDR(4),
243 "bad phys_addr (foo4)");
244 zassert_equal(rom_foo4->size, DT_INST_REG_SIZE(4),
245 "bad size (foo4)");
246 #else
247 zassert_equal(rom_foo3->addr, DT_INST_REG_ADDR(3),
248 "bad addr (foo3)");
249 zassert_equal(regs_foo3, rom_foo3->addr, "bad regs (foo3)");
250 zassert_equal(rom_foo4->addr, DT_INST_REG_ADDR(4),
251 "bad addr (foo4)");
252 zassert_equal(regs_foo4, rom_foo4->addr, "bad regs (foo4)");
253 #endif
254 }
255
256 /**
257 * @brief device_map() test
258 *
259 * Show that device_map() populates a memory address. We don't do anything else;
260 * tests for k_map() will prove that virtual memory mapping actually works.
261 */
ZTEST(device,test_mmio_device_map)262 ZTEST(device, test_mmio_device_map)
263 {
264 #ifdef DEVICE_MMIO_IS_IN_RAM
265 mm_reg_t regs = 0;
266
267 device_map(®s, 0xF0000000, 0x1000, K_MEM_CACHE_NONE);
268
269 zassert_not_equal(regs, 0, "bad regs");
270 #else
271 ztest_test_skip();
272 #endif
273 }
274