1 #include "FreeRTOS.h"
2 #include "hal_msgbox.h"
3 #include "msgbox_sx.h"
4 #include "../platform-msgbox.h"
5 #include "hal_interrupt.h"
6 #include "hal_log.h"
7 #include "string.h"
8 #include "hal_clk.h"
9
10 struct messagebox *msgbox_dsp;
11 struct messagebox *msgbox_cpu;
12
msgbox_sx_init_ccmu(void)13 int msgbox_sx_init_ccmu(void)
14 {
15 if (hal_clock_enable(HAL_CLK_PERIPH_MSGBOX0) < 0) {
16 hal_log_err("enable msgbox0 clk err!\n");
17 return -1;
18 }
19
20 if (hal_clock_enable(HAL_CLK_PERIPH_MSGBOX1) < 0) {
21 hal_log_err("enable msgbox1 clk err!\n");
22 return -1;
23 }
24
25 if (hal_clock_enable(HAL_CLK_PERIPH_MSGBOXR) < 0) {
26 hal_log_err("enable r_msgbox clk err!\n");
27 return -1;
28 }
29
30 return 0;
31 }
32
msgbox_init_sx(enum msgbox_direction dir)33 struct messagebox *msgbox_init_sx(enum msgbox_direction dir)
34 {
35 struct messagebox *mb = pvPortMalloc(sizeof(struct messagebox) +
36 sizeof(struct msg_channel) *
37 MSGBOX_MAX_QUEUE);
38
39 if (!mb)
40 return 0;
41
42 /* for reset and gating */
43
44 memset(mb, 0,
45 sizeof(struct messagebox) +
46 sizeof(struct msg_channel) * MSGBOX_MAX_QUEUE);
47 if (dir == MSGBOX_DIRECTION_DSP) {
48 mb->base = MSGBOX_DSP_DSP;
49 mb->this_user = MSGBOX_DSP_DSP_USER;
50 } else {
51 mb->base = MSGBOX_CPU_DSP;
52 mb->this_user = MSGBOX_CPU_DSP_USER;
53 }
54
55 msg_ops_init_sx(mb);
56
57 if (dir == MSGBOX_DIRECTION_CPU) {
58 irq_request(SUNXI_DSP_IRQ_MSGBOX0_DSP, msg_irq_handler_sx, mb);
59 irq_enable(SUNXI_DSP_IRQ_MSGBOX0_DSP);
60 } else {
61 irq_request(SUNXI_DSP_IRQ_R_MSGBOX_DSP, msg_irq_handler_sx, mb);
62 irq_enable(SUNXI_DSP_IRQ_R_MSGBOX_DSP);
63 }
64
65 return mb;
66 }
67
msgbox_uninit_sx(struct messagebox * mb)68 void msgbox_uninit_sx(struct messagebox *mb)
69 {
70 irq_free(SUNXI_DSP_IRQ_MSGBOX0_DSP);
71 vPortFree(mb);
72 }
73
74 /*
75 * msgbox_rev_handler - rev interrupt handler function
76 */
msgbox_rev_handler(int channel,void * c)77 static int msgbox_rev_handler(int channel, void *c)
78 {
79 struct msg_channel *ch = c;
80 struct messagebox *mb = ch->mb;
81 unsigned long data;
82
83 while (mb->channel_fifo_len(mb, channel) > 0) {
84 mb->channel_read(mb, channel, &data);
85 if (ch->cb_rx)
86 ch->cb_rx(data, ch->data);
87 }
88 return 0;
89 }
90
91 /*
92 * msgbox_send_handler - send interrutp handler function
93 */
msgbox_send_handler(int channel,void * c)94 static int msgbox_send_handler(int channel, void *c)
95 {
96 struct msg_channel *ch = c;
97 struct messagebox *mb = ch->mb;
98
99 while (mb->channel_fifo_len(mb, channel) < MSGBOX_CHANNEL_DEPTH) {
100 unsigned long i;
101 unsigned long data = 0;
102
103 if (ch->idx >= ch->len) {
104 goto finish;
105 }
106
107 for (i = 0; i < sizeof(long); i++) {
108 if (ch->idx < ch->len)
109 data |= ch->send[ch->idx++] << (i << 3);
110 }
111
112 mb->channel_write(mb, channel, data);
113
114 }
115
116 return 0;
117
118 finish:
119 mb->channel_irq_set(mb, channel, false);
120 if (ch->cb_tx_done)
121 ch->cb_tx_done(ch->idx, ch->data);
122
123 return 0;
124 }
125
126
127 /**
128 * msgbox_alloc_channel - alloc channel from msgbox
129 * @func when function as send, it act as tx_done
130 * when function as rev, it act as word reveive.
131 */
msgbox_alloc_channel_sx(struct messagebox * mb,int channel,enum msgbox_channel_direction dir,int (* func)(unsigned long,void *),void * data)132 struct msg_channel *msgbox_alloc_channel_sx(struct messagebox *mb, int channel,
133 enum msgbox_channel_direction dir,
134 int (*func)(unsigned long, void *),
135 void *data)
136 {
137 struct msg_channel *ch;
138
139 if (!mb || channel >= MSGBOX_MAX_QUEUE)
140 return 0;
141
142 ch = &mb->msg_handler[channel];
143
144 ch->mb = mb;
145 ch->channel = channel;
146 ch->data = data;
147 ch->dir = dir;
148
149 if (mb->channel_set_direction(mb, channel, dir))
150 return 0;
151
152 if (ch->dir == MSGBOX_CHANNEL_SEND) {
153 ch->cb_of_msg_queue = msgbox_send_handler;
154 ch->cb_tx_done = func;
155 }
156 else {
157 ch->cb_of_msg_queue = msgbox_rev_handler;
158 ch->cb_rx = func;
159
160 mb->channel_irq_set(mb, channel, true);
161 }
162
163 return ch;
164 }
165
msgbox_free_channel_sx(struct messagebox * mb,struct msg_channel * ch)166 void msgbox_free_channel_sx(struct messagebox *mb, struct msg_channel *ch)
167 {
168 if (!mb || ch->channel >= MSGBOX_MAX_QUEUE)
169 return;
170
171 mb->channel_irq_set(mb, ch->channel, false);
172
173 ch->data = NULL;
174 ch->cb_of_msg_queue = NULL;
175 ch->cb_tx_done = NULL;
176 ch->cb_rx = NULL;
177 }
178
msgbox_channel_send_data_sx(struct msg_channel * ch,unsigned char * d,size_t len)179 int msgbox_channel_send_data_sx(struct msg_channel *ch, unsigned char *d,
180 size_t len)
181 {
182 struct messagebox *mb = ch->mb;
183
184 ch->send = d;
185 ch->len = len;
186 ch->idx = 0;
187
188 mb->channel_irq_set(mb, ch->channel, true);
189
190 return 0;
191 }
192
messagebox_init_sx(void)193 int messagebox_init_sx(void)
194 {
195 msgbox_sx_init_ccmu();
196 msgbox_dsp = msgbox_init_sx(MSGBOX_DIRECTION_DSP);
197 msgbox_cpu = msgbox_init_sx(MSGBOX_DIRECTION_CPU);
198
199 return 0;
200 }
201
202