blob: 7dd3de34c9998f5ce8b93981010f7eec36a2698e [file] [log] [blame]
Simon Glass4bf89722020-12-23 08:11:18 -07001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (c) 2014 Google, Inc
4 */
5
6#include <common.h>
7#include <dm.h>
8#include <dm/test.h>
9
10/* Records the last testbus device that was removed */
11static struct udevice *testbus_removed;
12
13struct udevice *testbus_get_clear_removed(void)
14{
15 struct udevice *removed = testbus_removed;
16
17 testbus_removed = NULL;
18
19 return removed;
20}
21
22static int testbus_drv_probe(struct udevice *dev)
23{
24 if (!CONFIG_IS_ENABLED(OF_PLATDATA)) {
25 int ret;
26
27 ret = dm_scan_fdt_dev(dev);
28 if (ret)
29 return ret;
30 }
31
32 return 0;
33}
34
35static int testbus_child_post_bind(struct udevice *dev)
36{
37 struct dm_test_parent_plat *plat;
38
39 plat = dev_get_parent_plat(dev);
40 plat->bind_flag = 1;
41 plat->uclass_bind_flag = 2;
42
43 return 0;
44}
45
46static int testbus_child_pre_probe(struct udevice *dev)
47{
48 struct dm_test_parent_data *parent_data = dev_get_parent_priv(dev);
49
50 parent_data->flag += TEST_FLAG_CHILD_PROBED;
51
52 return 0;
53}
54
55static int testbus_child_pre_probe_uclass(struct udevice *dev)
56{
57 struct dm_test_priv *priv = dev_get_priv(dev);
58
59 priv->uclass_flag++;
60
61 return 0;
62}
63
64static int testbus_child_post_probe_uclass(struct udevice *dev)
65{
66 struct dm_test_priv *priv = dev_get_priv(dev);
67
68 priv->uclass_postp++;
69
70 return 0;
71}
72
73static int testbus_child_post_remove(struct udevice *dev)
74{
75 struct dm_test_parent_data *parent_data = dev_get_parent_priv(dev);
76
77 parent_data->flag += TEST_FLAG_CHILD_REMOVED;
78 testbus_removed = dev;
79
80 return 0;
81}
82
83static const struct udevice_id testbus_ids[] = {
84 { .compatible = "denx,u-boot-test-bus", .data = DM_TEST_TYPE_FIRST },
85 { }
86};
87
88U_BOOT_DRIVER(testbus_drv) = {
89 .name = "testbus_drv",
90 .of_match = testbus_ids,
91 .id = UCLASS_TEST_BUS,
92 .probe = testbus_drv_probe,
93 .child_post_bind = testbus_child_post_bind,
94 .priv_auto = sizeof(struct dm_test_priv),
95 .plat_auto = sizeof(struct dm_test_pdata),
96 .per_child_auto = sizeof(struct dm_test_parent_data),
97 .per_child_plat_auto = sizeof(struct dm_test_parent_plat),
98 .child_pre_probe = testbus_child_pre_probe,
99 .child_post_remove = testbus_child_post_remove,
100};
101
102UCLASS_DRIVER(testbus) = {
103 .name = "testbus",
104 .id = UCLASS_TEST_BUS,
105 .flags = DM_UC_FLAG_SEQ_ALIAS,
106 .child_pre_probe = testbus_child_pre_probe_uclass,
107 .child_post_probe = testbus_child_post_probe_uclass,
108};
109
110static int testfdt_drv_ping(struct udevice *dev, int pingval, int *pingret)
111{
112 const struct dm_test_pdata *pdata = dev_get_plat(dev);
113 struct dm_test_priv *priv = dev_get_priv(dev);
114
115 *pingret = pingval + pdata->ping_add;
116 priv->ping_total += *pingret;
117
118 return 0;
119}
120
121static const struct test_ops test_ops = {
122 .ping = testfdt_drv_ping,
123};
124
125static int testfdt_of_to_plat(struct udevice *dev)
126{
127 struct dm_test_pdata *pdata = dev_get_plat(dev);
128
129 pdata->ping_add = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
130 "ping-add", -1);
131 pdata->base = fdtdec_get_addr(gd->fdt_blob, dev_of_offset(dev),
132 "ping-expect");
133
134 return 0;
135}
136
137static int testfdt_drv_probe(struct udevice *dev)
138{
139 struct dm_test_priv *priv = dev_get_priv(dev);
140
141 priv->ping_total += DM_TEST_START_TOTAL;
142
143 /*
144 * If this device is on a bus, the uclass_flag will be set before
145 * calling this function. In the meantime the uclass_postp is
146 * initlized to a value -1. These are used respectively by
147 * dm_test_bus_child_pre_probe_uclass() and
148 * dm_test_bus_child_post_probe_uclass().
149 */
150 priv->uclass_total += priv->uclass_flag;
151 priv->uclass_postp = -1;
152
153 return 0;
154}
155
156static const struct udevice_id testfdt_ids[] = {
157 { .compatible = "denx,u-boot-fdt-test", .data = DM_TEST_TYPE_FIRST },
158 { .compatible = "google,another-fdt-test", .data = DM_TEST_TYPE_SECOND },
159 { }
160};
161
162U_BOOT_DRIVER(testfdt_drv) = {
163 .name = "testfdt_drv",
164 .of_match = testfdt_ids,
165 .id = UCLASS_TEST_FDT,
166 .of_to_plat = testfdt_of_to_plat,
167 .probe = testfdt_drv_probe,
168 .ops = &test_ops,
169 .priv_auto = sizeof(struct dm_test_priv),
170 .plat_auto = sizeof(struct dm_test_pdata),
171};
172
173static const struct udevice_id testfdt1_ids[] = {
174 { .compatible = "denx,u-boot-fdt-test1", .data = DM_TEST_TYPE_FIRST },
175 { }
176};
177
178U_BOOT_DRIVER(testfdt1_drv) = {
179 .name = "testfdt1_drv",
180 .of_match = testfdt1_ids,
181 .id = UCLASS_TEST_FDT,
182 .of_to_plat = testfdt_of_to_plat,
183 .probe = testfdt_drv_probe,
184 .ops = &test_ops,
185 .priv_auto = sizeof(struct dm_test_priv),
186 .plat_auto = sizeof(struct dm_test_pdata),
187 .flags = DM_FLAG_PRE_RELOC,
188};
189
190/* From here is the testfdt uclass code */
191int testfdt_ping(struct udevice *dev, int pingval, int *pingret)
192{
193 const struct test_ops *ops = device_get_ops(dev);
194
195 if (!ops->ping)
196 return -ENOSYS;
197
198 return ops->ping(dev, pingval, pingret);
199}
200
201UCLASS_DRIVER(testfdt) = {
202 .name = "testfdt",
203 .id = UCLASS_TEST_FDT,
204 .flags = DM_UC_FLAG_SEQ_ALIAS,
205};
206
207static const struct udevice_id testfdtm_ids[] = {
208 { .compatible = "denx,u-boot-fdtm-test" },
209 { }
210};
211
212U_BOOT_DRIVER(testfdtm_drv) = {
213 .name = "testfdtm_drv",
214 .of_match = testfdtm_ids,
215 .id = UCLASS_TEST_FDT_MANUAL,
216};
217
218UCLASS_DRIVER(testfdtm) = {
219 .name = "testfdtm",
220 .id = UCLASS_TEST_FDT_MANUAL,
221 .flags = DM_UC_FLAG_SEQ_ALIAS | DM_UC_FLAG_NO_AUTO_SEQ,
222};