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