863f5ef54ed57b2c95b8a51a2c17ce4c3ad91ef9
[fw/altos] / src / stmf0 / ao_crc_stm.c
1 /*
2  * Copyright © 2015 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; version 2 of the License.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
16  */
17
18 #include <ao.h>
19 #include <ao_crc.h>
20
21 #ifndef AO_CRC_WIDTH
22 #error "Must define AO_CRC_WIDTH"
23 #endif
24
25 /* Only the STM32F07x and ST32F09x series have
26  * programmable CRC units. Others can only do the ANSI CRC-32 computation
27  */
28
29 #if !AO_HAVE_PROGRAMMABLE_CRC_UNIT && AO_CRC_WIDTH != 32
30 #error "Target hardware does not have programmable CRC unit"
31 #endif
32
33 #ifndef AO_CRC_POLY
34 #if AO_CRC_WIDTH == 16
35 #define AO_CRC_POLY     AO_CRC_16_DEFAULT
36 #endif
37 #if AO_CRC_WIDTH == 32
38 #define AO_CRC_POLY     AO_CRC_32_DEFAULT
39 #endif
40 #endif
41
42 #if !AO_HAVE_PROGRAMMABLE_CRC_UNIT && (AO_CRC_WIDTH != 32 || AO_CRC_POLY != AO_CRC_32_ANSI)
43 #error "Target hardware does not have programmable CRC unit"
44 #endif
45
46 #if AO_CRC_WIDTH == 32
47 #define AO_CRC_CR_POLYSIZE      STM_CRC_CR_POLYSIZE_32
48 #endif
49
50 #if AO_CRC_WIDTH == 16
51 #define AO_CRC_CR_POLYSIZE      STM_CRC_CR_POLYSIZE_16
52 #endif
53
54 #if AO_CRC_WIDTH == 8
55 #define AO_CRC_CR_POLYSIZE      STM_CRC_CR_POLYSIZE_8
56 #endif
57
58 #if AO_CRC_WIDTH == 7
59 #define AO_CRC_CR_POLYSIZE      STM_CRC_CR_POLYSIZE_7
60 #endif
61
62 #ifndef AO_CRC_INIT
63 #define AO_CRC_INIT     0xffffffff
64 #endif
65
66 void
67 ao_crc_reset(void)
68 {
69         stm_crc.cr |= (1 << STM_CRC_CR_RESET);
70         while ((stm_crc.cr & (1 << STM_CRC_CR_RESET)) != 0)
71                 ;
72 }
73
74 void
75 ao_crc_init(void)
76 {
77         /* Turn on the CRC clock */
78         stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_CRCEN);
79
80         /* Need to initialize CR even on non-programmable hardware,
81          * the write to the POLYSIZE bits will be ignored in that
82          * case
83          */
84         stm_crc.cr = (AO_CRC_CR_POLYSIZE << STM_CRC_CR_POLYSIZE);
85         stm_crc.init = AO_CRC_INIT;
86 #if AO_HAVE_PROGRAMMABLE_CRC_UNIT
87         stm_crc.pol = AO_CRC_POLY;
88 #endif
89         ao_crc_reset();
90 }