1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <string.h> 18 19 #include <nanohub/crc.h> 20 #include <seos.h> 21 22 #include <plat/inc/pwr.h> 23 24 struct StmCrcRegs { 25 volatile uint32_t DR; 26 volatile uint32_t IDR; 27 volatile uint32_t CR; 28 }; 29 30 #define STM_CRC_CR_RESET 1 31 32 static uint32_t mRevCrcTab[] = 33 { 34 0x00000000, 0xB2B4BCB6, 0x61A864DB, 0xD31CD86D, 35 0xC350C9B6, 0x71E47500, 0xA2F8AD6D, 0x104C11DB, 36 0x82608EDB, 0x30D4326D, 0xE3C8EA00 ,0x517C56B6, 37 0x4130476D, 0xF384FBDB, 0x209823B6, 0x922C9F00 38 }; 39 40 static uint32_t revCrc32Word(uint32_t crc, uint32_t data, uint32_t cnt) 41 { 42 uint32_t i; 43 44 for (i = 0; i < cnt; i++) 45 crc = (crc >> 4) ^ mRevCrcTab[crc & 0x0F]; 46 47 return crc ^ data; 48 } 49 50 static struct StmCrcRegs *mCrcRegs = (struct StmCrcRegs *)CRC_BASE; 51 52 uint32_t crc32(const void *buf, size_t size, uint32_t crc) 53 { 54 const uint32_t *words = (const uint32_t *)buf; 55 size_t numWords = size / 4; 56 unsigned int leftoverBytes = size % 4; 57 size_t i; 58 59 pwrUnitClock(PERIPH_BUS_AHB1, PERIPH_AHB1_CRC, true); 60 61 if (mCrcRegs->DR == crc) 62 ; 63 else if (crc == CRC_INIT) 64 mCrcRegs->CR = STM_CRC_CR_RESET; 65 else 66 mCrcRegs->DR = revCrc32Word(crc, mCrcRegs->DR, 8); 67 68 for (i = 0; i < numWords; i++) 69 mCrcRegs->DR = words[i]; 70 71 if (leftoverBytes) { 72 uint32_t word = 0; 73 memcpy(&word, words + numWords, leftoverBytes); 74 /* n.b.: no shifting is needed, since the CRC block looks at the 75 * lowest byte first (i.e., we need the padding in the upper bytes) 76 */ 77 mCrcRegs->DR = word; 78 } 79 80 crc = mCrcRegs->DR; 81 pwrUnitClock(PERIPH_BUS_AHB1, PERIPH_AHB1_CRC, false); 82 return crc; 83 } 84