altoslib: fix computation of TeleGPS battery voltage
[fw/altos] / src / cc1111 / ao_aes.c
1 /*
2  * Copyright © 2011 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  */
18
19 #include "ao.h"
20
21 #if !HAS_AES
22 #error Must define HAS_AES 1
23 #endif
24
25 __xdata uint8_t ao_aes_mutex;
26 __xdata uint8_t ao_aes_done;
27 __xdata uint8_t ao_aes_dma_in, ao_aes_dma_out;
28 __xdata uint8_t ao_aes_dma_in_done, ao_aes_dma_out_done;
29 __pdata enum ao_aes_mode ao_aes_current_mode;
30
31 void
32 ao_aes_isr(void) __interrupt 4
33 {
34         S0CON = 0;
35         if (ENCCCS & ENCCCS_RDY) {
36                 ao_aes_done = 1;
37                 ao_wakeup(&ao_aes_done);
38         }
39 }
40
41 void
42 ao_aes_set_mode(enum ao_aes_mode mode)
43 {
44         ao_aes_current_mode = mode;
45 }
46
47 void
48 ao_aes_set_key(__xdata uint8_t *in)
49 {
50         ao_dma_set_transfer(ao_aes_dma_in,
51                             in,
52                             &ENCDIXADDR,
53                             AO_AES_LEN,
54                             DMA_CFG0_WORDSIZE_8 |
55                             DMA_CFG0_TMODE_SINGLE |
56                             DMA_CFG0_TRIGGER_ENC_DW,
57                             DMA_CFG1_SRCINC_1 |
58                             DMA_CFG1_DESTINC_0 |
59                             DMA_CFG1_PRIORITY_LOW);
60         ao_dma_start(ao_aes_dma_in);
61         ao_aes_done = 0;
62         ENCCCS = ENCCCS_MODE_CBC_MAC |
63                 ENCCCS_CMD_LOAD_KEY;
64         ENCCCS |= ENCCCS_START;
65         __critical while (!ao_aes_done)
66                 ao_sleep(&ao_aes_done);
67 }
68
69 void
70 ao_aes_zero_iv(void)
71 {
72         uint8_t b;
73
74         ENCCCS = ENCCCS_MODE_CBC_MAC | ENCCCS_CMD_LOAD_IV | ENCCCS_START;
75         for (b = 0; b < AO_AES_LEN; b++)
76                 ENCDI = 0;
77 }
78
79 void
80 ao_aes_run(__xdata uint8_t *in,
81            __xdata uint8_t *out)
82 {
83         uint8_t b;
84         if (in) {
85                 ao_dma_set_transfer(ao_aes_dma_in,
86                                     in,
87                                     &ENCDIXADDR,
88                                     AO_AES_LEN,
89                                     DMA_CFG0_WORDSIZE_8 |
90                                     DMA_CFG0_TMODE_SINGLE |
91                                     DMA_CFG0_TRIGGER_ENC_DW,
92                                     DMA_CFG1_SRCINC_1 |
93                                     DMA_CFG1_DESTINC_0 |
94                                     DMA_CFG1_PRIORITY_LOW);
95         }
96         if (out) {
97                 ao_dma_set_transfer(ao_aes_dma_out,
98                                     &ENCDOXADDR,
99                                     out,
100                                     AO_AES_LEN,
101                                     DMA_CFG0_WORDSIZE_8 |
102                                     DMA_CFG0_TMODE_SINGLE |
103                                     DMA_CFG0_TRIGGER_ENC_UP,
104                                     DMA_CFG1_SRCINC_0 |
105                                     DMA_CFG1_DESTINC_1 |
106                                     DMA_CFG1_PRIORITY_LOW);
107         }
108         switch (ao_aes_current_mode) {
109         case ao_aes_mode_cbc_mac:
110                 if (out)
111                         b = (ENCCCS_MODE_CBC |
112                              ENCCCS_CMD_ENCRYPT);
113                 else
114                         b = (ENCCCS_MODE_CBC_MAC |
115                              ENCCCS_CMD_ENCRYPT);
116                 break;
117         default:
118                 return;
119         }
120         ao_aes_done = 0;
121         if (in)
122                 ao_dma_start(ao_aes_dma_in);
123         if (out)
124                 ao_dma_start(ao_aes_dma_out);
125         ENCCCS = b;
126         ENCCCS |= ENCCCS_START;
127         if (out) {
128                 __critical while (!ao_aes_dma_out_done)
129                         ao_sleep(&ao_aes_dma_out_done);
130         } else {
131                 __critical while (!ao_aes_done)
132                         ao_sleep(&ao_aes_done);
133         }
134 }
135
136 void
137 ao_aes_init(void)
138 {
139 #if DMA_SHARE_AES_RADIO
140         ao_aes_dma_in = ao_radio_dma;
141 #else
142         ao_aes_dma_in = ao_dma_alloc(&ao_aes_dma_in_done);
143 #endif
144         ao_aes_dma_out = ao_dma_alloc(&ao_aes_dma_out_done);
145         S0CON = 0;
146         ENCIE = 1;
147 }