1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2014 Google, Inc
4  */
5 
6 #include <dm.h>
7 #include <dm/test.h>
8 #include <asm/global_data.h>
9 
10 /* Records the last testbus device that was removed */
11 static struct udevice *testbus_removed;
12 
testbus_get_clear_removed(void)13 struct udevice *testbus_get_clear_removed(void)
14 {
15 	struct udevice *removed = testbus_removed;
16 
17 	testbus_removed = NULL;
18 
19 	return removed;
20 }
21 
testbus_drv_probe(struct udevice * dev)22 static 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 
testbus_child_post_bind(struct udevice * dev)35 static 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 
testbus_child_pre_probe(struct udevice * dev)46 static 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 
testbus_child_pre_probe_uclass(struct udevice * dev)55 static 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 
testbus_child_post_probe_uclass(struct udevice * dev)64 static 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 
testbus_child_post_remove(struct udevice * dev)73 static 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 
83 static const struct udevice_id testbus_ids[] = {
84 	{ .compatible = "denx,u-boot-test-bus", .data = DM_TEST_TYPE_FIRST },
85 	{ }
86 };
87 
88 U_BOOT_DRIVER(denx_u_boot_test_bus) = {
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 	DM_HEADER(<test.h>)
101 };
102 
103 UCLASS_DRIVER(testbus) = {
104 	.name		= "testbus",
105 	.id		= UCLASS_TEST_BUS,
106 	.flags		= DM_UC_FLAG_SEQ_ALIAS,
107 	.child_pre_probe = testbus_child_pre_probe_uclass,
108 	.child_post_probe = testbus_child_post_probe_uclass,
109 
110 	.per_device_auto   = sizeof(struct dm_test_uclass_priv),
111 
112 	/* Note: this is for dtoc testing as well as tags*/
113 	.per_device_plat_auto   = sizeof(struct dm_test_uclass_plat),
114 };
115 
testfdt_drv_ping(struct udevice * dev,int pingval,int * pingret)116 static int testfdt_drv_ping(struct udevice *dev, int pingval, int *pingret)
117 {
118 	const struct dm_test_pdata *pdata = dev_get_plat(dev);
119 	struct dm_test_priv *priv = dev_get_priv(dev);
120 
121 	*pingret = pingval + pdata->ping_add;
122 	priv->ping_total += *pingret;
123 
124 	return 0;
125 }
126 
127 static const struct test_ops test_ops = {
128 	.ping = testfdt_drv_ping,
129 };
130 
testfdt_of_to_plat(struct udevice * dev)131 static int testfdt_of_to_plat(struct udevice *dev)
132 {
133 	struct dm_test_pdata *pdata = dev_get_plat(dev);
134 
135 	pdata->ping_add = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
136 					 "ping-add", -1);
137 	pdata->base = fdtdec_get_addr(gd->fdt_blob, dev_of_offset(dev),
138 				      "ping-expect");
139 
140 	return 0;
141 }
142 
testfdt_drv_probe(struct udevice * dev)143 static int testfdt_drv_probe(struct udevice *dev)
144 {
145 	struct dm_test_priv *priv = dev_get_priv(dev);
146 
147 	priv->ping_total += DM_TEST_START_TOTAL;
148 
149 	/*
150 	 * If this device is on a bus, the uclass_flag will be set before
151 	 * calling this function. In the meantime the uclass_postp is
152 	 * initlized to a value -1. These are used respectively by
153 	 * dm_test_bus_child_pre_probe_uclass() and
154 	 * dm_test_bus_child_post_probe_uclass().
155 	 */
156 	priv->uclass_total += priv->uclass_flag;
157 	priv->uclass_postp = -1;
158 
159 	return 0;
160 }
161 
162 static const struct udevice_id testfdt_ids[] = {
163 	{ .compatible = "denx,u-boot-fdt-test", .data = DM_TEST_TYPE_FIRST },
164 	{ .compatible = "google,another-fdt-test", .data = DM_TEST_TYPE_SECOND },
165 	{ }
166 };
167 
168 DM_DRIVER_ALIAS(denx_u_boot_fdt_test, google_another_fdt_test)
169 
170 U_BOOT_DRIVER(denx_u_boot_fdt_test) = {
171 	.name	= "testfdt_drv",
172 	.of_match	= testfdt_ids,
173 	.id	= UCLASS_TEST_FDT,
174 	.of_to_plat = testfdt_of_to_plat,
175 	.probe	= testfdt_drv_probe,
176 	.ops	= &test_ops,
177 	.priv_auto	= sizeof(struct dm_test_priv),
178 	.plat_auto	= sizeof(struct dm_test_pdata),
179 };
180 
181 static const struct udevice_id testfdt1_ids[] = {
182 	{ .compatible = "denx,u-boot-fdt-test1", .data = DM_TEST_TYPE_FIRST },
183 	{ }
184 };
185 
186 U_BOOT_DRIVER(testfdt1_drv) = {
187 	.name	= "testfdt1_drv",
188 	.of_match	= testfdt1_ids,
189 	.id	= UCLASS_TEST_FDT,
190 	.of_to_plat = testfdt_of_to_plat,
191 	.probe	= testfdt_drv_probe,
192 	.ops	= &test_ops,
193 	.priv_auto	= sizeof(struct dm_test_priv),
194 	.plat_auto	= sizeof(struct dm_test_pdata),
195 	.flags = DM_FLAG_PRE_RELOC,
196 };
197 
198 /* From here is the testfdt uclass code */
testfdt_ping(struct udevice * dev,int pingval,int * pingret)199 int testfdt_ping(struct udevice *dev, int pingval, int *pingret)
200 {
201 	const struct test_ops *ops = device_get_ops(dev);
202 
203 	if (!ops->ping)
204 		return -ENOSYS;
205 
206 	return ops->ping(dev, pingval, pingret);
207 }
208 
209 UCLASS_DRIVER(testfdt) = {
210 	.name		= "testfdt",
211 	.id		= UCLASS_TEST_FDT,
212 	.flags		= DM_UC_FLAG_SEQ_ALIAS,
213 	.priv_auto	= sizeof(struct dm_test_uc_priv),
214 };
215 
216 static const struct udevice_id testfdtm_ids[] = {
217 	{ .compatible = "denx,u-boot-fdtm-test" },
218 	{ }
219 };
220 
221 U_BOOT_DRIVER(testfdtm_drv) = {
222 	.name	= "testfdtm_drv",
223 	.of_match	= testfdtm_ids,
224 	.id	= UCLASS_TEST_FDT_MANUAL,
225 };
226 
227 UCLASS_DRIVER(testfdtm) = {
228 	.name		= "testfdtm",
229 	.id		= UCLASS_TEST_FDT_MANUAL,
230 	.flags		= DM_UC_FLAG_SEQ_ALIAS | DM_UC_FLAG_NO_AUTO_SEQ,
231 };
232