1  /*
2   * Copyright (c) 2020 Intel Corporation
3   *
4   * SPDX-License-Identifier: Apache-2.0
5   */
6  
7  #include <zephyr/kernel.h>
8  #include <zephyr/device.h>
9  #include <zephyr/init.h>
10  #include <zephyr/ztest.h>
11  #include <zephyr/linker/sections.h>
12  
13  
14  /**
15   * @brief Test cases to device driver initialization
16   *
17   */
18  
19  #define MY_DRIVER_LV_1    "my_driver_level_1"
20  #define MY_DRIVER_LV_2    "my_driver_level_2"
21  #define MY_DRIVER_LV_3    "my_driver_level_3"
22  #define MY_DRIVER_PRI_1    "my_driver_priority_1"
23  #define MY_DRIVER_PRI_2    "my_driver_priority_2"
24  #define MY_DRIVER_PRI_3    "my_driver_priority_3"
25  #define MY_DRIVER_PRI_4    "my_driver_priority_4"
26  
27  #define LEVEL_PRE_KERNEL_1	1
28  #define LEVEL_PRE_KERNEL_2	2
29  #define LEVEL_POST_KERNEL	3
30  
31  #define PRIORITY_1	1
32  #define PRIORITY_2	2
33  #define PRIORITY_3	3
34  #define PRIORITY_4	4
35  
36  
37  /* this is for storing sequence during initialization */
38  __pinned_bss int init_level_sequence[3] = {0};
39  __pinned_bss int init_priority_sequence[4] = {0};
40  __pinned_bss int init_sub_priority_sequence[3] = {0};
41  __pinned_bss unsigned int seq_level_cnt;
42  __pinned_bss unsigned int seq_priority_cnt;
43  __pinned_bss unsigned int seq_sub_priority_cnt;
44  
45  /* define driver type 1: for testing initialize levels and priorities */
46  typedef int (*my_api_configure_t)(const struct device *dev, int dev_config);
47  
48  struct my_driver_api {
49  	my_api_configure_t configure;
50  };
51  
my_configure(const struct device * dev,int config)52  static int my_configure(const struct device *dev, int config)
53  {
54  	return 0;
55  }
56  
57  static const struct my_driver_api funcs_my_drivers = {
58  	.configure = my_configure,
59  };
60  
61  /* driver init function of testing level */
62  __pinned_func
my_driver_lv_1_init(const struct device * dev)63  static int my_driver_lv_1_init(const struct device *dev)
64  {
65  	init_level_sequence[seq_level_cnt] = LEVEL_PRE_KERNEL_1;
66  	seq_level_cnt++;
67  
68  	return 0;
69  }
70  
71  __pinned_func
my_driver_lv_2_init(const struct device * dev)72  static int my_driver_lv_2_init(const struct device *dev)
73  {
74  	init_level_sequence[seq_level_cnt] = LEVEL_PRE_KERNEL_2;
75  	seq_level_cnt++;
76  
77  	return 0;
78  }
79  
my_driver_lv_3_init(const struct device * dev)80  static int my_driver_lv_3_init(const struct device *dev)
81  {
82  	init_level_sequence[seq_level_cnt] = LEVEL_POST_KERNEL;
83  	seq_level_cnt++;
84  
85  	return 0;
86  }
87  
88  /* driver init function of testing priority */
my_driver_pri_1_init(const struct device * dev)89  static int my_driver_pri_1_init(const struct device *dev)
90  {
91  	init_priority_sequence[seq_priority_cnt] = PRIORITY_1;
92  	seq_priority_cnt++;
93  
94  	return 0;
95  }
96  
my_driver_pri_2_init(const struct device * dev)97  static int my_driver_pri_2_init(const struct device *dev)
98  {
99  	init_priority_sequence[seq_priority_cnt] = PRIORITY_2;
100  	seq_priority_cnt++;
101  
102  	return 0;
103  }
104  
my_driver_pri_3_init(const struct device * dev)105  static int my_driver_pri_3_init(const struct device *dev)
106  {
107  	init_priority_sequence[seq_priority_cnt] = PRIORITY_3;
108  	seq_priority_cnt++;
109  
110  	return 0;
111  }
112  
my_driver_pri_4_init(const struct device * dev)113  static int my_driver_pri_4_init(const struct device *dev)
114  {
115  	init_priority_sequence[seq_priority_cnt] = PRIORITY_4;
116  	seq_priority_cnt++;
117  
118  	return 0;
119  }
120  
121  /* driver init function of testing sub_priority */
my_driver_sub_pri_0_init(const struct device * dev)122  static int my_driver_sub_pri_0_init(const struct device *dev)
123  {
124  	init_sub_priority_sequence[0] = seq_sub_priority_cnt++;
125  
126  	return 0;
127  }
128  
my_driver_sub_pri_1_init(const struct device * dev)129  static int my_driver_sub_pri_1_init(const struct device *dev)
130  {
131  	init_sub_priority_sequence[1] = seq_sub_priority_cnt++;
132  
133  	return 0;
134  }
135  
my_driver_sub_pri_2_init(const struct device * dev)136  static int my_driver_sub_pri_2_init(const struct device *dev)
137  {
138  	init_sub_priority_sequence[2] = seq_sub_priority_cnt++;
139  
140  	return 0;
141  }
142  
143  /**
144   * @brief Test providing control device driver initialization order
145   *
146   * @details Test that kernel shall provide control over device driver
147   * initialization order, using initialization level and priority for each
148   * instance. We use DEVICE_DEFINE to define device instances and set
149   * it's level and priority here, then we run check function later after
150   * all of this instance finish their initialization.
151   *
152   * @ingroup kernel_device_tests
153   */
154  DEVICE_DEFINE(my_driver_level_1, MY_DRIVER_LV_1, &my_driver_lv_1_init,
155  		NULL, NULL, NULL, PRE_KERNEL_1,
156  		CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &funcs_my_drivers);
157  
158  DEVICE_DEFINE(my_driver_level_2, MY_DRIVER_LV_2, &my_driver_lv_2_init,
159  		NULL, NULL, NULL, PRE_KERNEL_2,
160  		CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &funcs_my_drivers);
161  
162  DEVICE_DEFINE(my_driver_level_3, MY_DRIVER_LV_3, &my_driver_lv_3_init,
163  		NULL, NULL, NULL, POST_KERNEL,
164  		CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &funcs_my_drivers);
165  
166  /* We use priority value of 20 to create a possible sorting conflict with
167   * priority value of 2.  So if the linker sorting isn't working correctly
168   * we'll find out.
169   */
170  DEVICE_DEFINE(my_driver_priority_4, MY_DRIVER_PRI_4,
171  		&my_driver_pri_4_init, NULL, NULL, NULL, POST_KERNEL, 20,
172  		&funcs_my_drivers);
173  
174  DEVICE_DEFINE(my_driver_priority_1, MY_DRIVER_PRI_1,
175  		&my_driver_pri_1_init, NULL, NULL, NULL, POST_KERNEL, 1,
176  		&funcs_my_drivers);
177  
178  DEVICE_DEFINE(my_driver_priority_2, MY_DRIVER_PRI_2,
179  		&my_driver_pri_2_init, NULL, NULL, NULL, POST_KERNEL, 2,
180  		&funcs_my_drivers);
181  
182  DEVICE_DEFINE(my_driver_priority_3, MY_DRIVER_PRI_3,
183  		&my_driver_pri_3_init, NULL, NULL, NULL, POST_KERNEL, 3,
184  		&funcs_my_drivers);
185  
186  /* Create several devices at the same init priority that depend on each
187   * other in devicetree so that we can validate linker sorting.
188   */
189  DEVICE_DT_DEFINE(DT_NODELABEL(fakedomain_0), my_driver_sub_pri_0_init,
190  		NULL, NULL, NULL, POST_KERNEL, 33, NULL);
191  DEVICE_DT_DEFINE(DT_NODELABEL(fakedomain_1), my_driver_sub_pri_1_init,
192  		NULL, NULL, NULL, POST_KERNEL, 33, NULL);
193  DEVICE_DT_DEFINE(DT_NODELABEL(fakedomain_2), my_driver_sub_pri_2_init,
194  		NULL, NULL, NULL, POST_KERNEL, 33, NULL);
195