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