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