1 /*
2 * Copyright (c) 2025-2026 Texas Instruments Incorporated - https://www.ti.com
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 /*
8 * Device Preparation and Validation
9 *
10 * This module prepares and validates devices for operations by performing
11 * initialization checks and handling exclusive access constraints before device operations.
12 */
13
14 #include <assert.h>
15 #include <errno.h>
16 #include <common/debug.h>
17
18 #include <ti_device.h>
19 #include <ti_device_prepare.h>
20 #include <ti_host_idx_mapping.h>
21
22 /**
23 * device_prepare() - Look up a device and host, and validate access.
24 * @host_id: Host ID making the request.
25 * @id: Device ID to look up.
26 * @host_idx: If non-NULL, filled with the resolved host index on success.
27 * @dev: If non-NULL, filled with the device pointer on success.
28 * @exclusive: If true, enforce exclusive ownership — fails if the device is
29 * marked exclusive and the caller is not the owner.
30 *
31 * Return: 0 on success, negative error code otherwise.
32 */
device_prepare(uint8_t host_id,uint32_t id,uint8_t * host_idx,struct ti_device ** dev,bool exclusive)33 static int32_t device_prepare(uint8_t host_id, uint32_t id, uint8_t *host_idx,
34 struct ti_device **dev, bool exclusive)
35 {
36 struct ti_device *local_device;
37 uint8_t local_host_idx;
38
39 assert(dev != NULL || host_idx != NULL);
40
41 local_device = ti_device_api_lookup(id);
42 if (local_device == NULL) {
43 VERBOSE("BAD_DEVICE: dev_id=%d\n", id);
44 return -EINVAL;
45 }
46
47 if (local_device->initialized == 0U) {
48 return -EINVAL;
49 }
50
51 local_host_idx = ti_host_idx_lookup(host_id);
52 if (local_host_idx == TI_HOST_IDX_NONE) {
53 return -EINVAL;
54 }
55
56 if (exclusive && (local_device->exclusive != 0U) &&
57 (local_device->exclusive != local_host_idx)) {
58 VERBOSE("EXCLUSIVE_DEVICE: dev_id=%d holder=%d requester=%d\n",
59 id, local_device->exclusive, host_id);
60 return -EINVAL;
61 }
62
63 if (dev != NULL) {
64 *dev = local_device;
65 }
66 if (host_idx != NULL) {
67 *host_idx = local_host_idx;
68 }
69
70 return 0;
71 }
72
ti_device_prepare_exclusive(uint8_t host_id,uint32_t id,uint8_t * host_idx,struct ti_device ** device_ptr)73 int32_t ti_device_prepare_exclusive(uint8_t host_id, uint32_t id, uint8_t *host_idx,
74 struct ti_device **device_ptr)
75 {
76 int32_t ret;
77
78 /* Ensure devices are fully initialized to allow modification */
79 ret = ti_devices_init_rw();
80 if (ret != 0) {
81 return ret;
82 }
83
84 return device_prepare(host_id, id, host_idx, device_ptr, true);
85 }
86
ti_device_prepare_nonexclusive(uint8_t host_id,uint32_t id,uint8_t * host_idx,struct ti_device ** device_ptr)87 int32_t ti_device_prepare_nonexclusive(uint8_t host_id, uint32_t id, uint8_t *host_idx,
88 struct ti_device **device_ptr)
89 {
90 return device_prepare(host_id, id, host_idx, device_ptr, false);
91 }
92