1 #include "hal_msgbox.h"
2 #include "bitops.h"
3 #include "msgbox_sx.h"
4 #include "compiler_attributes.h"
5
6
7 #define MSGBOX_CTRL_REG_OFFSET 0x00
8 #define MSGBOX_VER_REG_OFFSET 0x10
9 #define MSGBOX_IRQ_EN_REG_OFFSET 0x40
10 #define MSGBOX_IRQ_STATUS_OFFSET 0x50
11 #define MSGBOX_FIFO_STATUS_OFFSET 0x100
12 #define MSGBOX_FIFO_STATUS_MASK BIT(0)
13 #define MSGBOX_MSG_STATUS_OFFSET 0x140
14 #define MSGBOX_MSG_STATUS_MASK 0x0f
15 #define MSGBOX_MSG_QUEUE_OFFSET 0x180
16
msg_queue_t_set(struct messagebox * mb,int queue)17 static int msg_queue_t_set(struct messagebox *mb, int queue)
18 {
19 int user = mb->this_user;
20 int offset_reg = (queue / 4 ) * 4 + MSGBOX_CTRL_REG_OFFSET;
21 int offset_bit_t = 4 + ((queue % 4) * 8 );
22 int offset_bit_r = ((queue % 4) * 8 );
23 unsigned long *reg = (unsigned long *)(mb->base + offset_reg);
24 unsigned long data;
25
26 if (queue >= MSGBOX_MAX_QUEUE || user >= MSGBOX_MAX_USER)
27 return -EINVAL;
28
29 data = *reg;
30 data &= ~(BIT(offset_bit_r) | BIT(offset_bit_t));
31
32 if (user)
33 *reg = data | BIT(offset_bit_t);
34 else
35 *reg = data | BIT(offset_bit_r);
36
37 return 0;
38 }
39
msg_queue_r_set(struct messagebox * mb,int queue)40 static int msg_queue_r_set(struct messagebox *mb, int queue)
41 {
42 int user = mb->this_user;
43 int offset_reg = (queue / 4 ) * 4 + MSGBOX_CTRL_REG_OFFSET;
44 int offset_bit_t = 4 + ((queue % 4) * 8 );
45 int offset_bit_r = ((queue % 4) * 8 );
46 unsigned long *reg = (unsigned long *)(mb->base + offset_reg);
47 unsigned long data;
48
49 if (queue >= MSGBOX_MAX_QUEUE || user >= MSGBOX_MAX_USER)
50 return -EINVAL;
51
52 data = *reg;
53 data &= ~(BIT(offset_bit_r) | BIT(offset_bit_t));
54
55 if (user)
56 *reg = data | BIT(offset_bit_r);
57 else
58 *reg = data | BIT(offset_bit_t);
59
60 return 0;
61 }
62
msg_queue_irq_t(struct messagebox * mb,int queue,int en)63 static int msg_queue_irq_t(struct messagebox *mb, int queue, int en)
64 {
65 int user = mb->this_user;
66 long *reg = (long *)(mb->base + MSGBOX_IRQ_EN_REG_OFFSET + user * 0x20);
67 int offset_bit = 1 + (queue << 1);
68
69 if (queue >= MSGBOX_MAX_QUEUE || user >= MSGBOX_MAX_USER)
70 return -EINVAL;
71
72 if (en)
73 *reg = SET_BIT(*reg, offset_bit);
74 else
75 *reg = CLR_BIT(*reg, offset_bit);
76
77 return 0;
78 }
79
msg_queue_irq_r(struct messagebox * mb,int queue,int en)80 static int msg_queue_irq_r(struct messagebox *mb, int queue, int en)
81 {
82 int user = mb->this_user;
83 long *reg = (long *)(mb->base + MSGBOX_IRQ_EN_REG_OFFSET + user * 0x20);
84 int offset_bit = (queue << 1);
85
86 if (queue >= MSGBOX_MAX_QUEUE || user >= MSGBOX_MAX_USER)
87 return -EINVAL;
88
89 if (en)
90 *reg = SET_BIT(*reg, offset_bit);
91 else
92 *reg = CLR_BIT(*reg, offset_bit);
93
94 return 0;
95 }
96
97 /*
98 * static int msg_queue_status_pending(struct messagebox *mb, int queue)
99 * {
100 * int user = mb->this_user;
101 *
102 * if (queue >= MSGBOX_MAX_QUEUE || user >= MSGBOX_MAX_USER)
103 * return -EINVAL;
104 *
105 * return 0;
106 * }
107 */
108
msg_queue_is_full(struct messagebox * mb,int queue)109 static __maybe_unused int msg_queue_is_full(struct messagebox *mb, int queue)
110 {
111 long *reg = (long *)(mb->base + MSGBOX_FIFO_STATUS_OFFSET + queue * 4);
112
113 if (queue >= MSGBOX_MAX_QUEUE)
114 return -EINVAL;
115
116 if (*reg & MSGBOX_FIFO_STATUS_MASK)
117 return 1;
118
119 return 0;
120 }
121
msg_queue_msg_cnt_sx(struct messagebox * mb,int queue)122 static int msg_queue_msg_cnt_sx(struct messagebox *mb, int queue)
123 {
124 long *reg = (long *)(mb->base + MSGBOX_MSG_STATUS_OFFSET + 4 * queue);
125
126 if (queue >= MSGBOX_MAX_QUEUE)
127 return -EINVAL;
128
129 return *reg & MSGBOX_MSG_STATUS_MASK;
130 }
131
msg_queue_read_sx(struct messagebox * mb,int queue,unsigned long * read)132 static int msg_queue_read_sx(struct messagebox *mb, int queue, unsigned long *read)
133 {
134 long *reg = (long *)(mb->base + MSGBOX_MSG_QUEUE_OFFSET + 4 * queue);
135
136 *read = *reg;
137
138 return 0;
139 }
140
msg_queue_write_sx(struct messagebox * mb,int queue,unsigned long write)141 static int msg_queue_write_sx(struct messagebox *mb, int queue,
142 unsigned long write)
143 {
144 long *reg = (long *)(mb->base + MSGBOX_MSG_QUEUE_OFFSET + 4 * queue);
145
146 *reg = write;
147
148 return 0;
149 }
150
msg_irq_enable_get(struct messagebox * mb)151 static inline unsigned long msg_irq_enable_get(struct messagebox *mb)
152 {
153 int user = mb->this_user;
154 long *reg = (long *)(mb->base + MSGBOX_IRQ_EN_REG_OFFSET + user * 0x20);
155
156 return *reg;
157 }
158
msg_irq_status(struct messagebox * mb)159 static inline unsigned long msg_irq_status(struct messagebox *mb)
160 {
161 int user = mb->this_user;
162 long *reg = (long *)(mb->base + MSGBOX_IRQ_STATUS_OFFSET + 0x20 * user);
163
164 if (user >= MSGBOX_MAX_USER)
165 return -EINVAL;
166
167 return *reg;
168 }
169
msg_irq_clear(struct messagebox * mb,unsigned long clr)170 static inline int msg_irq_clear(struct messagebox *mb, unsigned long clr)
171 {
172 int user = mb->this_user;
173 long *reg = (long *)(mb->base + MSGBOX_IRQ_STATUS_OFFSET + 0x20 * user);
174
175 if (user >= MSGBOX_MAX_USER)
176 return -EINVAL;
177
178 *reg = clr;
179
180 return 0;
181 }
182
msg_irq_handler_sx(int i,void * d)183 int msg_irq_handler_sx(int i, void *d)
184 {
185 int channel;
186 struct messagebox *mb = d;
187 unsigned long status = msg_irq_status(mb);
188 unsigned long enable = msg_irq_enable_get(mb);
189
190
191 for (channel = 0; channel < MSGBOX_MAX_QUEUE; channel++) {
192 unsigned long tbit = channel << 1;
193 struct msg_channel *h = &mb->msg_handler[channel];
194
195 tbit = (1 << tbit) | (1 << (tbit + 1));
196 if ((tbit & status & enable) && h->cb_of_msg_queue) {
197 h->cb_of_msg_queue(channel, h);
198 }
199 }
200
201 msg_irq_clear(mb, status & enable);
202
203 return 0;
204 }
205
206 static inline int
msg_channel_set_direction_sx(struct messagebox * mb,int channel,enum msgbox_channel_direction dir)207 msg_channel_set_direction_sx(struct messagebox *mb, int channel,
208 enum msgbox_channel_direction dir)
209 {
210 if (dir == MSGBOX_CHANNEL_SEND)
211 return msg_queue_t_set(mb, channel);
212 else
213 return msg_queue_r_set(mb, channel);
214 }
215
msg_channel_irq_set_sx(struct messagebox * mb,int channel,int enable)216 static inline int msg_channel_irq_set_sx(struct messagebox *mb, int channel,
217 int enable)
218 {
219 struct msg_channel *ch;
220
221 if (channel >= MSGBOX_MAX_QUEUE)
222 return -EINVAL;
223
224 ch = &mb->msg_handler[channel];
225 if (ch->dir == MSGBOX_CHANNEL_SEND)
226 return msg_queue_irq_t(mb, channel, enable);
227 else
228 return msg_queue_irq_r(mb, channel, enable);
229 }
230
msg_ops_init_sx(struct messagebox * mb)231 int msg_ops_init_sx(struct messagebox *mb)
232 {
233
234 mb->channel_set_direction = msg_channel_set_direction_sx;
235 mb->channel_irq_set = msg_channel_irq_set_sx;
236 mb->channel_fifo_len = msg_queue_msg_cnt_sx;
237 mb->channel_read = msg_queue_read_sx;
238 mb->channel_write = msg_queue_write_sx;
239
240 return 0;
241 }
242
243