1 /*
2 * this is only for , adopt to other must change the m and n.
3 */
4 #include "../platform-msgbox.h"
5 #include "hal_msgbox.h"
6 #include "hal_interrupt.h"
7 #include "aw_io.h"
8 #include "hal_clk.h"
9 #include "hal_reset.h"
10
11
12 static struct msg_endpoint *it_edp = NULL;
13 #define MSGBOX_MAX_QUEUE 8
14
calculte_n(int local,int remote)15 static inline int calculte_n(int local, int remote)
16 {
17 if (remote < local)
18 return remote;
19 else
20 return remote - 1;
21 }
22
irq_msgbox_channel_handler(struct msg_endpoint * medp)23 static void irq_msgbox_channel_handler(struct msg_endpoint *medp)
24 {
25 void *msg_sts, *msg_reg, *msg_irq_s;
26 u32 data;
27
28 msg_sts = (void *)MSGBOX_MSG_STA_REG(
29 medp->local_amp, calculte_n(medp->local_amp, medp->remote_amp),
30 medp->read_ch);
31 msg_reg = (void *)MSGBOX_MSG_REG(
32 medp->local_amp, calculte_n(medp->local_amp, medp->remote_amp),
33 medp->read_ch);
34 msg_irq_s = (void *)MSGBOX_RD_IRQ_STA_REG(
35 medp->local_amp, calculte_n(medp->local_amp, medp->remote_amp));
36
37 while (readl(msg_sts)) {
38 data = readl(msg_reg);
39 if (medp->rec)
40 medp->rec(data, medp->private);
41 }
42
43 writel(1 << (medp->read_ch * 2), msg_irq_s);
44 }
45
irq_msgbox_handler(int i,void * p)46 static int irq_msgbox_handler(int i, void *p)
47 {
48 struct msg_endpoint *t;
49
50 for (t = it_edp; t != NULL; t = t->next) {
51 irq_msgbox_channel_handler(t);
52 }
53
54 return 0;
55 }
56
hal_msgbox_init(void)57 uint32_t hal_msgbox_init(void)
58 {
59 struct reset_control *rst;
60 hal_clk_t clk;
61
62 rst = hal_reset_control_get(HAL_SUNXI_RESET, RST_MSGBOX);
63 hal_reset_control_deassert(rst);
64 hal_reset_control_put(rst);
65
66 clk = hal_clock_get(HAL_SUNXI_CCU, CLK_MSGBOX);
67 hal_clock_enable(clk);
68 hal_clock_put(clk);
69
70 irq_request(IRQ_MSGBOX, irq_msgbox_handler, it_edp);
71 irq_enable(IRQ_MSGBOX);
72
73 return 0;
74 }
75
msgbox_enable_rec_int(struct msg_endpoint * medp)76 static void msgbox_enable_rec_int(struct msg_endpoint *medp)
77 {
78 void *msg_irq_e;
79
80 msg_irq_e = (void *)MSGBOX_RD_IRQ_EN_REG(
81 medp->local_amp, calculte_n(medp->local_amp, medp->remote_amp));
82
83 writel(1 << (medp->read_ch * 2), msg_irq_e);
84
85 }
86
hal_msgbox_alloc_channel(struct msg_endpoint * edp,uint32_t remote,uint32_t read,uint32_t write)87 uint32_t hal_msgbox_alloc_channel(struct msg_endpoint *edp, uint32_t remote,
88 uint32_t read, uint32_t write)
89 {
90 edp->local_amp = THIS_MSGBOX_USE;
91 edp->remote_amp = remote;
92 edp->read_ch = read;
93 edp->write_ch = write;
94
95 /* add to global list */
96 if (it_edp == NULL) {
97 it_edp = edp;
98 } else {
99
100 struct msg_endpoint *t = it_edp;
101
102 while (t) {
103
104 if (t->next == NULL) {
105 t->next = edp;
106 break;
107 }
108
109 t = t->next;
110 }
111 }
112
113 edp->next = NULL;
114
115 msgbox_enable_rec_int(edp);
116
117 return 0;
118 }
119
120
msgbox_channel_send_data(struct msg_endpoint * medp,u32 data)121 static void msgbox_channel_send_data(struct msg_endpoint *medp, u32 data)
122 {
123 void *msg_sts, *msg_reg;
124
125 msg_sts = (void *)MSGBOX_MSG_STA_REG(
126 medp->remote_amp, calculte_n(medp->remote_amp, medp->local_amp),
127 medp->write_ch);
128 msg_reg = (void *)MSGBOX_MSG_REG(
129 medp->remote_amp, calculte_n(medp->remote_amp, medp->local_amp),
130 medp->write_ch);
131
132 while (readl(msg_sts) == MSGBOX_MAX_QUEUE);
133 writel(data, msg_reg);
134 }
135
hal_msgbox_channel_send(struct msg_endpoint * medp,uint8_t * bf,uint32_t len)136 u32 hal_msgbox_channel_send(struct msg_endpoint *medp, uint8_t *bf,
137 uint32_t len)
138 {
139 u32 data, i;
140
141 for (i = 0; i < len; i++) {
142
143 if (!(i % 4))
144 data = 0;
145
146 data |= *bf++ << ((i % 4) << 3);
147
148 if ((i % 4) == 3 || i == len - 1) {
149 msgbox_channel_send_data(medp, data);
150 }
151 }
152
153 return 0;
154 }
155
156
157