diff options
author | Suzuki K. Poulose <suzuki.poulose@arm.com> | 2015-03-18 08:24:38 -0400 |
---|---|---|
committer | Will Deacon <will.deacon@arm.com> | 2015-03-27 09:44:15 -0400 |
commit | f6b9e83ce05e362f4190cf2b4281d85cd094e541 (patch) | |
tree | 4ac34422b3914cb2ac9a82c1c185db6d6c62ac37 /drivers/bus | |
parent | b1862199be6098855b598b69f5098d2fb4cecfcb (diff) |
arm-cci: Rearrange code for splitting PMU vs driver code
No functional changes, only code re-arrangements for easier split of the
PMU code vs low level driver code. Extracts the port handling code
to cci_probe_ports().
Tested-by: Sudeep Holla <sudeep.holla@arm.com>
Acked-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Acked-by: Punit Agrawal <punit.agrawal@arm.com>
Signed-off-by: Suzuki K. Poulose <suzuki.poulose@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'drivers/bus')
-rw-r--r-- | drivers/bus/arm-cci.c | 326 |
1 files changed, 163 insertions, 163 deletions
diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c index 68ef6f2aa24d..5d29ec34078e 100644 --- a/drivers/bus/arm-cci.c +++ b/drivers/bus/arm-cci.c | |||
@@ -29,42 +29,29 @@ | |||
29 | #include <asm/cacheflush.h> | 29 | #include <asm/cacheflush.h> |
30 | #include <asm/smp_plat.h> | 30 | #include <asm/smp_plat.h> |
31 | 31 | ||
32 | #define DRIVER_NAME "CCI-400" | 32 | static void __iomem *cci_ctrl_base; |
33 | #define DRIVER_NAME_PMU DRIVER_NAME " PMU" | 33 | static unsigned long cci_ctrl_phys; |
34 | |||
35 | #define CCI_PORT_CTRL 0x0 | ||
36 | #define CCI_CTRL_STATUS 0xc | ||
37 | |||
38 | #define CCI_ENABLE_SNOOP_REQ 0x1 | ||
39 | #define CCI_ENABLE_DVM_REQ 0x2 | ||
40 | #define CCI_ENABLE_REQ (CCI_ENABLE_SNOOP_REQ | CCI_ENABLE_DVM_REQ) | ||
41 | 34 | ||
42 | struct cci_nb_ports { | 35 | struct cci_nb_ports { |
43 | unsigned int nb_ace; | 36 | unsigned int nb_ace; |
44 | unsigned int nb_ace_lite; | 37 | unsigned int nb_ace_lite; |
45 | }; | 38 | }; |
46 | 39 | ||
47 | enum cci_ace_port_type { | 40 | static const struct cci_nb_ports cci400_ports = { |
48 | ACE_INVALID_PORT = 0x0, | 41 | .nb_ace = 2, |
49 | ACE_PORT, | 42 | .nb_ace_lite = 3 |
50 | ACE_LITE_PORT, | ||
51 | }; | 43 | }; |
52 | 44 | ||
53 | struct cci_ace_port { | 45 | static const struct of_device_id arm_cci_matches[] = { |
54 | void __iomem *base; | 46 | {.compatible = "arm,cci-400", .data = &cci400_ports }, |
55 | unsigned long phys; | 47 | {}, |
56 | enum cci_ace_port_type type; | ||
57 | struct device_node *dn; | ||
58 | }; | 48 | }; |
59 | 49 | ||
60 | static struct cci_ace_port *ports; | ||
61 | static unsigned int nb_cci_ports; | ||
62 | |||
63 | static void __iomem *cci_ctrl_base; | ||
64 | static unsigned long cci_ctrl_phys; | ||
65 | |||
66 | #ifdef CONFIG_HW_PERF_EVENTS | 50 | #ifdef CONFIG_HW_PERF_EVENTS |
67 | 51 | ||
52 | #define DRIVER_NAME "CCI-400" | ||
53 | #define DRIVER_NAME_PMU DRIVER_NAME " PMU" | ||
54 | |||
68 | #define CCI_PMCR 0x0100 | 55 | #define CCI_PMCR 0x0100 |
69 | #define CCI_PID2 0x0fe8 | 56 | #define CCI_PID2 0x0fe8 |
70 | 57 | ||
@@ -75,6 +62,47 @@ static unsigned long cci_ctrl_phys; | |||
75 | #define CCI_PID2_REV_MASK 0xf0 | 62 | #define CCI_PID2_REV_MASK 0xf0 |
76 | #define CCI_PID2_REV_SHIFT 4 | 63 | #define CCI_PID2_REV_SHIFT 4 |
77 | 64 | ||
65 | #define CCI_PMU_EVT_SEL 0x000 | ||
66 | #define CCI_PMU_CNTR 0x004 | ||
67 | #define CCI_PMU_CNTR_CTRL 0x008 | ||
68 | #define CCI_PMU_OVRFLW 0x00c | ||
69 | |||
70 | #define CCI_PMU_OVRFLW_FLAG 1 | ||
71 | |||
72 | #define CCI_PMU_CNTR_BASE(idx) ((idx) * SZ_4K) | ||
73 | |||
74 | #define CCI_PMU_CNTR_MASK ((1ULL << 32) -1) | ||
75 | |||
76 | #define CCI_PMU_EVENT_MASK 0xff | ||
77 | #define CCI_PMU_EVENT_SOURCE(event) ((event >> 5) & 0x7) | ||
78 | #define CCI_PMU_EVENT_CODE(event) (event & 0x1f) | ||
79 | |||
80 | #define CCI_PMU_MAX_HW_EVENTS 5 /* CCI PMU has 4 counters + 1 cycle counter */ | ||
81 | |||
82 | struct cci_pmu_hw_events { | ||
83 | struct perf_event *events[CCI_PMU_MAX_HW_EVENTS]; | ||
84 | unsigned long used_mask[BITS_TO_LONGS(CCI_PMU_MAX_HW_EVENTS)]; | ||
85 | raw_spinlock_t pmu_lock; | ||
86 | }; | ||
87 | |||
88 | struct cci_pmu { | ||
89 | void __iomem *base; | ||
90 | struct pmu pmu; | ||
91 | int nr_irqs; | ||
92 | int irqs[CCI_PMU_MAX_HW_EVENTS]; | ||
93 | unsigned long active_irqs; | ||
94 | struct pmu_port_event_ranges *port_ranges; | ||
95 | struct cci_pmu_hw_events hw_events; | ||
96 | struct platform_device *plat_device; | ||
97 | int num_events; | ||
98 | atomic_t active_events; | ||
99 | struct mutex reserve_mutex; | ||
100 | cpumask_t cpus; | ||
101 | }; | ||
102 | static struct cci_pmu *pmu; | ||
103 | |||
104 | #define to_cci_pmu(c) (container_of(c, struct cci_pmu, pmu)) | ||
105 | |||
78 | /* Port ids */ | 106 | /* Port ids */ |
79 | #define CCI_PORT_S0 0 | 107 | #define CCI_PORT_S0 0 |
80 | #define CCI_PORT_S1 1 | 108 | #define CCI_PORT_S1 1 |
@@ -89,17 +117,6 @@ static unsigned long cci_ctrl_phys; | |||
89 | #define CCI_REV_R1 1 | 117 | #define CCI_REV_R1 1 |
90 | #define CCI_REV_R1_PX 5 | 118 | #define CCI_REV_R1_PX 5 |
91 | 119 | ||
92 | #define CCI_PMU_EVT_SEL 0x000 | ||
93 | #define CCI_PMU_CNTR 0x004 | ||
94 | #define CCI_PMU_CNTR_CTRL 0x008 | ||
95 | #define CCI_PMU_OVRFLW 0x00c | ||
96 | |||
97 | #define CCI_PMU_OVRFLW_FLAG 1 | ||
98 | |||
99 | #define CCI_PMU_CNTR_BASE(idx) ((idx) * SZ_4K) | ||
100 | |||
101 | #define CCI_PMU_CNTR_MASK ((1ULL << 32) -1) | ||
102 | |||
103 | /* | 120 | /* |
104 | * Instead of an event id to monitor CCI cycles, a dedicated counter is | 121 | * Instead of an event id to monitor CCI cycles, a dedicated counter is |
105 | * provided. Use 0xff to represent CCI cycles and hope that no future revisions | 122 | * provided. Use 0xff to represent CCI cycles and hope that no future revisions |
@@ -109,12 +126,6 @@ enum cci400_perf_events { | |||
109 | CCI_PMU_CYCLES = 0xff | 126 | CCI_PMU_CYCLES = 0xff |
110 | }; | 127 | }; |
111 | 128 | ||
112 | #define CCI_PMU_EVENT_MASK 0xff | ||
113 | #define CCI_PMU_EVENT_SOURCE(event) ((event >> 5) & 0x7) | ||
114 | #define CCI_PMU_EVENT_CODE(event) (event & 0x1f) | ||
115 | |||
116 | #define CCI_PMU_MAX_HW_EVENTS 5 /* CCI PMU has 4 counters + 1 cycle counter */ | ||
117 | |||
118 | #define CCI_PMU_CYCLE_CNTR_IDX 0 | 129 | #define CCI_PMU_CYCLE_CNTR_IDX 0 |
119 | #define CCI_PMU_CNTR0_IDX 1 | 130 | #define CCI_PMU_CNTR0_IDX 1 |
120 | #define CCI_PMU_CNTR_LAST(cci_pmu) (CCI_PMU_CYCLE_CNTR_IDX + cci_pmu->num_events - 1) | 131 | #define CCI_PMU_CNTR_LAST(cci_pmu) (CCI_PMU_CYCLE_CNTR_IDX + cci_pmu->num_events - 1) |
@@ -172,60 +183,6 @@ static char *const pmu_names[] = { | |||
172 | [CCI_REV_R1] = "CCI_400_r1", | 183 | [CCI_REV_R1] = "CCI_400_r1", |
173 | }; | 184 | }; |
174 | 185 | ||
175 | struct cci_pmu_hw_events { | ||
176 | struct perf_event *events[CCI_PMU_MAX_HW_EVENTS]; | ||
177 | unsigned long used_mask[BITS_TO_LONGS(CCI_PMU_MAX_HW_EVENTS)]; | ||
178 | raw_spinlock_t pmu_lock; | ||
179 | }; | ||
180 | |||
181 | struct cci_pmu { | ||
182 | void __iomem *base; | ||
183 | struct pmu pmu; | ||
184 | int nr_irqs; | ||
185 | int irqs[CCI_PMU_MAX_HW_EVENTS]; | ||
186 | unsigned long active_irqs; | ||
187 | struct pmu_port_event_ranges *port_ranges; | ||
188 | struct cci_pmu_hw_events hw_events; | ||
189 | struct platform_device *plat_device; | ||
190 | int num_events; | ||
191 | atomic_t active_events; | ||
192 | struct mutex reserve_mutex; | ||
193 | cpumask_t cpus; | ||
194 | }; | ||
195 | static struct cci_pmu *pmu; | ||
196 | |||
197 | #define to_cci_pmu(c) (container_of(c, struct cci_pmu, pmu)) | ||
198 | |||
199 | static bool is_duplicate_irq(int irq, int *irqs, int nr_irqs) | ||
200 | { | ||
201 | int i; | ||
202 | |||
203 | for (i = 0; i < nr_irqs; i++) | ||
204 | if (irq == irqs[i]) | ||
205 | return true; | ||
206 | |||
207 | return false; | ||
208 | } | ||
209 | |||
210 | static int probe_cci_revision(void) | ||
211 | { | ||
212 | int rev; | ||
213 | rev = readl_relaxed(cci_ctrl_base + CCI_PID2) & CCI_PID2_REV_MASK; | ||
214 | rev >>= CCI_PID2_REV_SHIFT; | ||
215 | |||
216 | if (rev < CCI_REV_R1_PX) | ||
217 | return CCI_REV_R0; | ||
218 | else | ||
219 | return CCI_REV_R1; | ||
220 | } | ||
221 | |||
222 | static struct pmu_port_event_ranges *port_range_by_rev(void) | ||
223 | { | ||
224 | int rev = probe_cci_revision(); | ||
225 | |||
226 | return &port_event_range[rev]; | ||
227 | } | ||
228 | |||
229 | static int pmu_is_valid_slave_event(u8 ev_code) | 186 | static int pmu_is_valid_slave_event(u8 ev_code) |
230 | { | 187 | { |
231 | return pmu->port_ranges->slave_min <= ev_code && | 188 | return pmu->port_ranges->slave_min <= ev_code && |
@@ -265,6 +222,25 @@ static int pmu_validate_hw_event(u8 hw_event) | |||
265 | return -ENOENT; | 222 | return -ENOENT; |
266 | } | 223 | } |
267 | 224 | ||
225 | static int probe_cci_revision(void) | ||
226 | { | ||
227 | int rev; | ||
228 | rev = readl_relaxed(cci_ctrl_base + CCI_PID2) & CCI_PID2_REV_MASK; | ||
229 | rev >>= CCI_PID2_REV_SHIFT; | ||
230 | |||
231 | if (rev < CCI_REV_R1_PX) | ||
232 | return CCI_REV_R0; | ||
233 | else | ||
234 | return CCI_REV_R1; | ||
235 | } | ||
236 | |||
237 | static struct pmu_port_event_ranges *port_range_by_rev(void) | ||
238 | { | ||
239 | int rev = probe_cci_revision(); | ||
240 | |||
241 | return &port_event_range[rev]; | ||
242 | } | ||
243 | |||
268 | static int pmu_is_valid_counter(struct cci_pmu *cci_pmu, int idx) | 244 | static int pmu_is_valid_counter(struct cci_pmu *cci_pmu, int idx) |
269 | { | 245 | { |
270 | return CCI_PMU_CYCLE_CNTR_IDX <= idx && | 246 | return CCI_PMU_CYCLE_CNTR_IDX <= idx && |
@@ -902,6 +878,17 @@ static const struct of_device_id arm_cci_pmu_matches[] = { | |||
902 | {}, | 878 | {}, |
903 | }; | 879 | }; |
904 | 880 | ||
881 | static bool is_duplicate_irq(int irq, int *irqs, int nr_irqs) | ||
882 | { | ||
883 | int i; | ||
884 | |||
885 | for (i = 0; i < nr_irqs; i++) | ||
886 | if (irq == irqs[i]) | ||
887 | return true; | ||
888 | |||
889 | return false; | ||
890 | } | ||
891 | |||
905 | static int cci_pmu_probe(struct platform_device *pdev) | 892 | static int cci_pmu_probe(struct platform_device *pdev) |
906 | { | 893 | { |
907 | struct resource *res; | 894 | struct resource *res; |
@@ -972,8 +959,65 @@ static int cci_platform_probe(struct platform_device *pdev) | |||
972 | return of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); | 959 | return of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); |
973 | } | 960 | } |
974 | 961 | ||
962 | static struct platform_driver cci_pmu_driver = { | ||
963 | .driver = { | ||
964 | .name = DRIVER_NAME_PMU, | ||
965 | .of_match_table = arm_cci_pmu_matches, | ||
966 | }, | ||
967 | .probe = cci_pmu_probe, | ||
968 | }; | ||
969 | |||
970 | static struct platform_driver cci_platform_driver = { | ||
971 | .driver = { | ||
972 | .name = DRIVER_NAME, | ||
973 | .of_match_table = arm_cci_matches, | ||
974 | }, | ||
975 | .probe = cci_platform_probe, | ||
976 | }; | ||
977 | |||
978 | static int __init cci_platform_init(void) | ||
979 | { | ||
980 | int ret; | ||
981 | |||
982 | ret = platform_driver_register(&cci_pmu_driver); | ||
983 | if (ret) | ||
984 | return ret; | ||
985 | |||
986 | return platform_driver_register(&cci_platform_driver); | ||
987 | } | ||
988 | |||
989 | #else /* !CONFIG_HW_PERF_EVENTS */ | ||
990 | |||
991 | static int __init cci_platform_init(void) | ||
992 | { | ||
993 | return 0; | ||
994 | } | ||
995 | |||
975 | #endif /* CONFIG_HW_PERF_EVENTS */ | 996 | #endif /* CONFIG_HW_PERF_EVENTS */ |
976 | 997 | ||
998 | #define CCI_PORT_CTRL 0x0 | ||
999 | #define CCI_CTRL_STATUS 0xc | ||
1000 | |||
1001 | #define CCI_ENABLE_SNOOP_REQ 0x1 | ||
1002 | #define CCI_ENABLE_DVM_REQ 0x2 | ||
1003 | #define CCI_ENABLE_REQ (CCI_ENABLE_SNOOP_REQ | CCI_ENABLE_DVM_REQ) | ||
1004 | |||
1005 | enum cci_ace_port_type { | ||
1006 | ACE_INVALID_PORT = 0x0, | ||
1007 | ACE_PORT, | ||
1008 | ACE_LITE_PORT, | ||
1009 | }; | ||
1010 | |||
1011 | struct cci_ace_port { | ||
1012 | void __iomem *base; | ||
1013 | unsigned long phys; | ||
1014 | enum cci_ace_port_type type; | ||
1015 | struct device_node *dn; | ||
1016 | }; | ||
1017 | |||
1018 | static struct cci_ace_port *ports; | ||
1019 | static unsigned int nb_cci_ports; | ||
1020 | |||
977 | struct cpu_port { | 1021 | struct cpu_port { |
978 | u64 mpidr; | 1022 | u64 mpidr; |
979 | u32 port; | 1023 | u32 port; |
@@ -1293,36 +1337,20 @@ int notrace __cci_control_port_by_index(u32 port, bool enable) | |||
1293 | } | 1337 | } |
1294 | EXPORT_SYMBOL_GPL(__cci_control_port_by_index); | 1338 | EXPORT_SYMBOL_GPL(__cci_control_port_by_index); |
1295 | 1339 | ||
1296 | static const struct cci_nb_ports cci400_ports = { | ||
1297 | .nb_ace = 2, | ||
1298 | .nb_ace_lite = 3 | ||
1299 | }; | ||
1300 | |||
1301 | static const struct of_device_id arm_cci_matches[] = { | ||
1302 | {.compatible = "arm,cci-400", .data = &cci400_ports }, | ||
1303 | {}, | ||
1304 | }; | ||
1305 | |||
1306 | static const struct of_device_id arm_cci_ctrl_if_matches[] = { | 1340 | static const struct of_device_id arm_cci_ctrl_if_matches[] = { |
1307 | {.compatible = "arm,cci-400-ctrl-if", }, | 1341 | {.compatible = "arm,cci-400-ctrl-if", }, |
1308 | {}, | 1342 | {}, |
1309 | }; | 1343 | }; |
1310 | 1344 | ||
1311 | static int cci_probe(void) | 1345 | static int cci_probe_ports(struct device_node *np) |
1312 | { | 1346 | { |
1313 | struct cci_nb_ports const *cci_config; | 1347 | struct cci_nb_ports const *cci_config; |
1314 | int ret, i, nb_ace = 0, nb_ace_lite = 0; | 1348 | int ret, i, nb_ace = 0, nb_ace_lite = 0; |
1315 | struct device_node *np, *cp; | 1349 | struct device_node *cp; |
1316 | struct resource res; | 1350 | struct resource res; |
1317 | const char *match_str; | 1351 | const char *match_str; |
1318 | bool is_ace; | 1352 | bool is_ace; |
1319 | 1353 | ||
1320 | np = of_find_matching_node(NULL, arm_cci_matches); | ||
1321 | if (!np) | ||
1322 | return -ENODEV; | ||
1323 | |||
1324 | if (!of_device_is_available(np)) | ||
1325 | return -ENODEV; | ||
1326 | 1354 | ||
1327 | cci_config = of_match_node(arm_cci_matches, np)->data; | 1355 | cci_config = of_match_node(arm_cci_matches, np)->data; |
1328 | if (!cci_config) | 1356 | if (!cci_config) |
@@ -1334,17 +1362,6 @@ static int cci_probe(void) | |||
1334 | if (!ports) | 1362 | if (!ports) |
1335 | return -ENOMEM; | 1363 | return -ENOMEM; |
1336 | 1364 | ||
1337 | ret = of_address_to_resource(np, 0, &res); | ||
1338 | if (!ret) { | ||
1339 | cci_ctrl_base = ioremap(res.start, resource_size(&res)); | ||
1340 | cci_ctrl_phys = res.start; | ||
1341 | } | ||
1342 | if (ret || !cci_ctrl_base) { | ||
1343 | WARN(1, "unable to ioremap CCI ctrl\n"); | ||
1344 | ret = -ENXIO; | ||
1345 | goto memalloc_err; | ||
1346 | } | ||
1347 | |||
1348 | for_each_child_of_node(np, cp) { | 1365 | for_each_child_of_node(np, cp) { |
1349 | if (!of_match_node(arm_cci_ctrl_if_matches, cp)) | 1366 | if (!of_match_node(arm_cci_ctrl_if_matches, cp)) |
1350 | continue; | 1367 | continue; |
@@ -1404,12 +1421,31 @@ static int cci_probe(void) | |||
1404 | sync_cache_w(&cpu_port); | 1421 | sync_cache_w(&cpu_port); |
1405 | __sync_cache_range_w(ports, sizeof(*ports) * nb_cci_ports); | 1422 | __sync_cache_range_w(ports, sizeof(*ports) * nb_cci_ports); |
1406 | pr_info("ARM CCI driver probed\n"); | 1423 | pr_info("ARM CCI driver probed\n"); |
1424 | |||
1407 | return 0; | 1425 | return 0; |
1426 | } | ||
1408 | 1427 | ||
1409 | memalloc_err: | 1428 | static int cci_probe(void) |
1429 | { | ||
1430 | int ret; | ||
1431 | struct device_node *np; | ||
1432 | struct resource res; | ||
1410 | 1433 | ||
1411 | kfree(ports); | 1434 | np = of_find_matching_node(NULL, arm_cci_matches); |
1412 | return ret; | 1435 | if(!np || !of_device_is_available(np)) |
1436 | return -ENODEV; | ||
1437 | |||
1438 | ret = of_address_to_resource(np, 0, &res); | ||
1439 | if (!ret) { | ||
1440 | cci_ctrl_base = ioremap(res.start, resource_size(&res)); | ||
1441 | cci_ctrl_phys = res.start; | ||
1442 | } | ||
1443 | if (ret || !cci_ctrl_base) { | ||
1444 | WARN(1, "unable to ioremap CCI ctrl\n"); | ||
1445 | return -ENXIO; | ||
1446 | } | ||
1447 | |||
1448 | return cci_probe_ports(np); | ||
1413 | } | 1449 | } |
1414 | 1450 | ||
1415 | static int cci_init_status = -EAGAIN; | 1451 | static int cci_init_status = -EAGAIN; |
@@ -1427,42 +1463,6 @@ static int cci_init(void) | |||
1427 | return cci_init_status; | 1463 | return cci_init_status; |
1428 | } | 1464 | } |
1429 | 1465 | ||
1430 | #ifdef CONFIG_HW_PERF_EVENTS | ||
1431 | static struct platform_driver cci_pmu_driver = { | ||
1432 | .driver = { | ||
1433 | .name = DRIVER_NAME_PMU, | ||
1434 | .of_match_table = arm_cci_pmu_matches, | ||
1435 | }, | ||
1436 | .probe = cci_pmu_probe, | ||
1437 | }; | ||
1438 | |||
1439 | static struct platform_driver cci_platform_driver = { | ||
1440 | .driver = { | ||
1441 | .name = DRIVER_NAME, | ||
1442 | .of_match_table = arm_cci_matches, | ||
1443 | }, | ||
1444 | .probe = cci_platform_probe, | ||
1445 | }; | ||
1446 | |||
1447 | static int __init cci_platform_init(void) | ||
1448 | { | ||
1449 | int ret; | ||
1450 | |||
1451 | ret = platform_driver_register(&cci_pmu_driver); | ||
1452 | if (ret) | ||
1453 | return ret; | ||
1454 | |||
1455 | return platform_driver_register(&cci_platform_driver); | ||
1456 | } | ||
1457 | |||
1458 | #else | ||
1459 | |||
1460 | static int __init cci_platform_init(void) | ||
1461 | { | ||
1462 | return 0; | ||
1463 | } | ||
1464 | |||
1465 | #endif | ||
1466 | /* | 1466 | /* |
1467 | * To sort out early init calls ordering a helper function is provided to | 1467 | * To sort out early init calls ordering a helper function is provided to |
1468 | * check if the CCI driver has beed initialized. Function check if the driver | 1468 | * check if the CCI driver has beed initialized. Function check if the driver |