1 /*
2 * Copyright (c) 2017, Texas Instruments Incorporated
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/sys/__assert.h>
9 #include <kernel/zephyr/dpl/dpl.h>
10 #include <ti/drivers/dpl/SemaphoreP.h>
11
12 /*
13 * Zephyr kernel object pools:
14 *
15 * This bit of code enables the simplelink host driver, which assumes dynamic
16 * allocation of kernel objects (semaphores, mutexes, hwis), to be
17 * more easily ported to Zephyr (which supports static allocation).
18 *
19 * It leverages the Zephyr memory slab, enabling us to define a semaphore
20 * object pool for use by the SimpleLink host driver.
21 */
22 #define DPL_MAX_SEMAPHORES 14 /* (user.h:MAX_CONCURRENT_ACTIONS+4) = 14 */
23 K_MEM_SLAB_DEFINE(sem_slab, sizeof(struct k_sem), DPL_MAX_SEMAPHORES,\
24 MEM_ALIGN);
25
dpl_sem_pool_alloc()26 static struct k_sem *dpl_sem_pool_alloc()
27 {
28 struct k_sem *sem_ptr = NULL;
29
30 if (k_mem_slab_alloc(&sem_slab, (void **)&sem_ptr, K_NO_WAIT) < 0) {
31 /*
32 * We assert, as this is a logic error, due to a change in #
33 * of semaphores needed by the simplelink driver. In that case,
34 * the sem pool must be increased programmatically to match.
35 */
36 __ASSERT(0, "Increase size of DPL semaphore pool");
37 }
38 return sem_ptr;
39 }
40
dpl_sem_pool_free(struct k_sem * sem)41 static SemaphoreP_Status dpl_sem_pool_free(struct k_sem *sem)
42 {
43 k_mem_slab_free(&sem_slab, (void **)&sem);
44
45 return SemaphoreP_OK;
46 }
47
48 /* timeout comes in and out in ticks */
dpl_convert_timeout(uint32_t timeout)49 static k_timeout_t dpl_convert_timeout(uint32_t timeout)
50 {
51 switch(timeout) {
52 case SemaphoreP_NO_WAIT:
53 return K_NO_WAIT;
54 case SemaphoreP_WAIT_FOREVER:
55 return K_FOREVER;
56 default:
57 return K_TICKS(timeout);
58 }
59 }
60
61
SemaphoreP_create(unsigned int count,SemaphoreP_Params * params)62 SemaphoreP_Handle SemaphoreP_create(unsigned int count,
63 SemaphoreP_Params *params)
64 {
65 unsigned int limit = UINT_MAX;
66 struct k_sem *sem;
67
68 if (params) {
69 limit = (params->mode == SemaphoreP_Mode_BINARY) ?
70 1 : UINT_MAX;
71 }
72
73 sem = dpl_sem_pool_alloc();
74 if (sem) {
75 k_sem_init(sem, count, limit);
76 }
77
78 return (SemaphoreP_Handle)sem;
79 }
80
SemaphoreP_createBinary(unsigned int count)81 SemaphoreP_Handle SemaphoreP_createBinary(unsigned int count)
82 {
83 SemaphoreP_Params params;
84
85 SemaphoreP_Params_init(¶ms);
86 params.mode = SemaphoreP_Mode_BINARY;
87
88 return (SemaphoreP_create(count, ¶ms));
89 }
90
91
SemaphoreP_delete(SemaphoreP_Handle handle)92 void SemaphoreP_delete(SemaphoreP_Handle handle)
93 {
94 k_sem_reset((struct k_sem *)handle);
95
96 (void)dpl_sem_pool_free((struct k_sem *)handle);
97 }
98
SemaphoreP_Params_init(SemaphoreP_Params * params)99 void SemaphoreP_Params_init(SemaphoreP_Params *params)
100 {
101 params->mode = SemaphoreP_Mode_COUNTING;
102 params->callback = NULL;
103 }
104
105 /*
106 * The SimpleLink driver calls this function with a timeout of 0 to "clear"
107 * the SyncObject, rather than calling dpl_SyncObjClear() directly.
108 * See: <simplelinksdk>/source/ti/drivers/net/wifi/source/driver.h
109 * #define SL_DRV_SYNC_OBJ_CLEAR(pObj)
110 * (void)sl_SyncObjWait(pObj,SL_OS_NO_WAIT);
111 *
112 * So, we claim (via simplelink driver code inspection), that SyncObjWait
113 * will *only* be called with timeout == 0 if the intention is to clear the
114 * semaphore: in that case, we just call k_sem_reset.
115 */
SemaphoreP_pend(SemaphoreP_Handle handle,uint32_t timeout)116 SemaphoreP_Status SemaphoreP_pend(SemaphoreP_Handle handle, uint32_t timeout)
117 {
118 int retval;
119
120 if (0 == timeout) {
121 k_sem_reset((struct k_sem *)handle);
122 retval = SemaphoreP_OK;
123 } else {
124 retval = k_sem_take((struct k_sem *)handle,
125 dpl_convert_timeout(timeout));
126 __ASSERT_NO_MSG(retval != -EBUSY);
127 retval = (retval >= 0) ? SemaphoreP_OK : SemaphoreP_TIMEOUT;
128 }
129 return retval;
130 }
131
SemaphoreP_post(SemaphoreP_Handle handle)132 void SemaphoreP_post(SemaphoreP_Handle handle)
133 {
134 k_sem_give((struct k_sem *)handle);
135 }
136
SemaphoreP_construct(SemaphoreP_Struct * handle,unsigned int count,SemaphoreP_Params * params)137 SemaphoreP_Handle SemaphoreP_construct(SemaphoreP_Struct *handle,
138 unsigned int count, SemaphoreP_Params *params)
139 {
140 unsigned int limit = UINT_MAX;
141 struct k_sem *sem;
142
143 if (params) {
144 limit = (params->mode == SemaphoreP_Mode_BINARY) ?
145 1 : UINT_MAX;
146 }
147
148 sem = (struct k_sem *)handle;
149 if (sem) {
150 k_sem_init(sem, count, limit);
151 }
152
153 return (SemaphoreP_Handle)sem;
154 }
155
SemaphoreP_constructBinary(SemaphoreP_Struct * handle,unsigned int count)156 SemaphoreP_Handle SemaphoreP_constructBinary(SemaphoreP_Struct *handle, unsigned int count) {
157 SemaphoreP_Params params;
158
159 SemaphoreP_Params_init(¶ms);
160 params.mode = SemaphoreP_Mode_BINARY;
161
162 return (SemaphoreP_construct(handle, count, ¶ms));
163 }
164
SemaphoreP_destruct(SemaphoreP_Struct * semP)165 void SemaphoreP_destruct(SemaphoreP_Struct *semP) {
166 struct k_sem *sem;
167
168 sem = (struct k_sem *)semP->data;
169 if (sem) {
170 k_sem_reset(sem);
171 }
172 }
173