1 // SPDX-License-Identifier: GPL-2.0-only 2 /* CRC32c (Castagnoli), sparc64 crc32c opcode accelerated 3 * 4 * This is based largely upon arch/x86/crypto/crc32c-intel.c 5 * 6 * Copyright (C) 2008 Intel Corporation 7 * Authors: Austin Zhang <austin_zhang@linux.intel.com> 8 * Kent Liu <kent.liu@intel.com> 9 */ 10 11 #include <asm/pstate.h> 12 #include <asm/elf.h> 13 14 static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_crc32c_opcode); 15 16 #define crc32_le_arch crc32_le_base /* not implemented on this arch */ 17 #define crc32_be_arch crc32_be_base /* not implemented on this arch */ 18 19 void crc32c_sparc64(u32 *crcp, const u64 *data, size_t len); 20 21 static inline u32 crc32c_arch(u32 crc, const u8 *data, size_t len) 22 { 23 size_t n = -(uintptr_t)data & 7; 24 25 if (!static_branch_likely(&have_crc32c_opcode)) 26 return crc32c_base(crc, data, len); 27 28 if (n) { 29 /* Data isn't 8-byte aligned. Align it. */ 30 n = min(n, len); 31 crc = crc32c_base(crc, data, n); 32 data += n; 33 len -= n; 34 } 35 n = len & ~7U; 36 if (n) { 37 crc32c_sparc64(&crc, (const u64 *)data, n); 38 data += n; 39 len -= n; 40 } 41 if (len) 42 crc = crc32c_base(crc, data, len); 43 return crc; 44 } 45 46 #define crc32_mod_init_arch crc32_mod_init_arch 47 static inline void crc32_mod_init_arch(void) 48 { 49 unsigned long cfr; 50 51 if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO)) 52 return; 53 54 __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr)); 55 if (!(cfr & CFR_CRC32C)) 56 return; 57 58 static_branch_enable(&have_crc32c_opcode); 59 pr_info("Using sparc64 crc32c opcode optimized CRC32C implementation\n"); 60 } 61 62 static inline u32 crc32_optimizations_arch(void) 63 { 64 if (static_key_enabled(&have_crc32c_opcode)) 65 return CRC32C_OPTIMIZATION; 66 return 0; 67 } 68