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