Merge tag 'dm-pull-28nov21' of https://source.denx.de/u-boot/custodians/u-boot-dm...
[platform/kernel/u-boot.git] / test / dm / spi.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2013 Google, Inc
4  */
5
6 #include <common.h>
7 #include <dm.h>
8 #include <fdtdec.h>
9 #include <spi.h>
10 #include <spi_flash.h>
11 #include <asm/state.h>
12 #include <asm/test.h>
13 #include <dm/device-internal.h>
14 #include <dm/test.h>
15 #include <dm/uclass-internal.h>
16 #include <dm/util.h>
17 #include <test/test.h>
18 #include <test/ut.h>
19
20 /* Test that we can find buses and chip-selects */
21 static int dm_test_spi_find(struct unit_test_state *uts)
22 {
23         struct sandbox_state *state = state_get_current();
24         struct spi_slave *slave;
25         struct udevice *bus, *dev;
26         const int busnum = 0, cs = 0, mode = 0, speed = 1000000, cs_b = 2;
27         struct spi_cs_info info;
28         ofnode node;
29
30         /*
31          * The post_bind() method will bind devices to chip selects. Check
32          * this then remove the emulation and the slave device.
33          */
34         ut_asserteq(0, uclass_get_device_by_seq(UCLASS_SPI, busnum, &bus));
35         ut_assertok(spi_cs_info(bus, cs, &info));
36         node = dev_ofnode(info.dev);
37         device_remove(info.dev, DM_REMOVE_NORMAL);
38         device_unbind(info.dev);
39
40         /*
41          * Even though the device is gone, the sandbox SPI drivers always
42          * reports that CS 0 is present
43          */
44         ut_assertok(spi_cs_info(bus, cs, &info));
45         ut_asserteq_ptr(NULL, info.dev);
46
47         /* This finds nothing because we removed the device */
48         ut_asserteq(-ENODEV, spi_find_bus_and_cs(busnum, cs, &bus, &dev));
49         ut_asserteq(-ENODEV, spi_get_bus_and_cs(busnum, cs, speed, mode,
50                                                 NULL, 0, &bus, &slave));
51
52         /*
53          * This forces the device to be re-added, but there is no emulation
54          * connected so the probe will fail. We require that bus is left
55          * alone on failure, and that the spi_get_bus_and_cs() does not add
56          * a 'partially-inited' device.
57          */
58         ut_asserteq(-ENODEV, spi_find_bus_and_cs(busnum, cs, &bus, &dev));
59         ut_asserteq(-ENOENT, spi_get_bus_and_cs(busnum, cs, speed, mode,
60                                                 "jedec_spi_nor", "name", &bus,
61                                                 &slave));
62         sandbox_sf_unbind_emul(state_get_current(), busnum, cs);
63         ut_assertok(spi_cs_info(bus, cs, &info));
64         ut_asserteq_ptr(NULL, info.dev);
65
66         /* Add the emulation and try again */
67         ut_assertok(sandbox_sf_bind_emul(state, busnum, cs, bus, node,
68                                          "name"));
69         ut_assertok(spi_find_bus_and_cs(busnum, cs, &bus, &dev));
70         ut_assertok(spi_get_bus_and_cs(busnum, cs, speed, mode,
71                                        "jedec_spi_nor", "name", &bus, &slave));
72
73         ut_assertok(spi_cs_info(bus, cs, &info));
74         ut_asserteq_ptr(info.dev, slave->dev);
75
76         /* We should be able to add something to another chip select */
77         ut_assertok(sandbox_sf_bind_emul(state, busnum, cs_b, bus, node,
78                                          "name"));
79         ut_asserteq(-EINVAL, spi_get_bus_and_cs(busnum, cs_b, speed, mode,
80                                        "jedec_spi_nor", "name", &bus, &slave));
81         ut_asserteq(-EINVAL, spi_cs_info(bus, cs_b, &info));
82         ut_asserteq_ptr(NULL, info.dev);
83
84         /*
85          * Since we are about to destroy all devices, we must tell sandbox
86          * to forget the emulation device
87          */
88         sandbox_sf_unbind_emul(state_get_current(), busnum, cs);
89         sandbox_sf_unbind_emul(state_get_current(), busnum, cs_b);
90
91         return 0;
92 }
93 DM_TEST(dm_test_spi_find, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
94
95 /* dm_test_spi_switch_slaves - Helper function to check whether spi_claim_bus
96  *                             operates correctly with two spi slaves.
97  *
98  * Check that switching back and forth between two slaves claiming the bus
99  * will update dm_spi_bus->speed and sandbox_spi bus speed/mode correctly.
100  *
101  * @uts - unit test state
102  * @slave_a - first spi slave used for testing
103  * @slave_b - second spi slave used for testing
104  */
105 static int dm_test_spi_switch_slaves(struct unit_test_state *uts,
106                                      struct spi_slave *slave_a,
107                                      struct spi_slave *slave_b)
108 {
109         struct udevice *bus;
110         struct dm_spi_bus *bus_data;
111
112         /* Check that slaves are on the same bus */
113         ut_asserteq_ptr(dev_get_parent(slave_a->dev),
114                         dev_get_parent(slave_b->dev));
115
116         bus = dev_get_parent(slave_a->dev);
117         bus_data = dev_get_uclass_priv(bus);
118
119         ut_assertok(spi_claim_bus(slave_a));
120         ut_asserteq(slave_a->max_hz, bus_data->speed);
121         ut_asserteq(slave_a->max_hz, sandbox_spi_get_speed(bus));
122         ut_asserteq(slave_a->mode, sandbox_spi_get_mode(bus));
123         spi_release_bus(slave_a);
124
125         ut_assertok(spi_claim_bus(slave_b));
126         ut_asserteq(slave_b->max_hz, bus_data->speed);
127         ut_asserteq(slave_b->max_hz, sandbox_spi_get_speed(bus));
128         ut_asserteq(slave_b->mode, sandbox_spi_get_mode(bus));
129         spi_release_bus(slave_b);
130
131         ut_assertok(spi_claim_bus(slave_a));
132         ut_asserteq(slave_a->max_hz, bus_data->speed);
133         ut_asserteq(slave_a->max_hz, sandbox_spi_get_speed(bus));
134         ut_asserteq(slave_a->mode, sandbox_spi_get_mode(bus));
135         spi_release_bus(slave_a);
136
137         return 0;
138 }
139
140 static int dm_test_spi_claim_bus(struct unit_test_state *uts)
141 {
142         struct udevice *bus;
143         struct spi_slave *slave_a, *slave_b;
144         struct dm_spi_slave_plat *slave_plat;
145         const int busnum = 0, cs_a = 0, cs_b = 1, mode = 0;
146
147         /* Get spi slave on CS0 */
148         ut_assertok(spi_get_bus_and_cs(busnum, cs_a, 1000000, mode, NULL, 0,
149                                        &bus, &slave_a));
150         /* Get spi slave on CS1 */
151         ut_assertok(spi_get_bus_and_cs(busnum, cs_b, 1000000, mode, NULL, 0,
152                                        &bus, &slave_b));
153
154         /* Different max_hz, different mode. */
155         ut_assert(slave_a->max_hz != slave_b->max_hz);
156         ut_assert(slave_a->mode != slave_b->mode);
157         dm_test_spi_switch_slaves(uts, slave_a, slave_b);
158
159         /* Different max_hz, same mode. */
160         slave_a->mode = slave_b->mode;
161         dm_test_spi_switch_slaves(uts, slave_a, slave_b);
162
163         /*
164          * Same max_hz, different mode.
165          * Restore original mode for slave_a, from platdata.
166          */
167         slave_plat = dev_get_parent_plat(slave_a->dev);
168         slave_a->mode = slave_plat->mode;
169         slave_a->max_hz = slave_b->max_hz;
170         dm_test_spi_switch_slaves(uts, slave_a, slave_b);
171
172         return 0;
173 }
174 DM_TEST(dm_test_spi_claim_bus, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
175
176 /* Test that sandbox SPI works correctly */
177 static int dm_test_spi_xfer(struct unit_test_state *uts)
178 {
179         struct spi_slave *slave;
180         struct udevice *bus;
181         const int busnum = 0, cs = 0, mode = 0;
182         const char dout[5] = {0x9f};
183         unsigned char din[5];
184
185         ut_assertok(spi_get_bus_and_cs(busnum, cs, 1000000, mode, NULL, 0,
186                                        &bus, &slave));
187         ut_assertok(spi_claim_bus(slave));
188         ut_assertok(spi_xfer(slave, 40, dout, din,
189                              SPI_XFER_BEGIN | SPI_XFER_END));
190         ut_asserteq(0xff, din[0]);
191         ut_asserteq(0x20, din[1]);
192         ut_asserteq(0x20, din[2]);
193         ut_asserteq(0x15, din[3]);
194         spi_release_bus(slave);
195
196         /*
197          * Since we are about to destroy all devices, we must tell sandbox
198          * to forget the emulation device
199          */
200 #if CONFIG_IS_ENABLED(DM_SPI_FLASH)
201         sandbox_sf_unbind_emul(state_get_current(), busnum, cs);
202 #endif
203
204         return 0;
205 }
206 DM_TEST(dm_test_spi_xfer, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);