1 /* 2 * CAAM/SEC 4.x functions for using scatterlists in caam driver 3 * 4 * Copyright 2008-2011 Freescale Semiconductor, Inc. 5 * 6 */ 7 8 #include "regs.h" 9 10 struct sec4_sg_entry { 11 u64 ptr; 12 u32 len; 13 u32 bpid_offset; 14 }; 15 16 /* 17 * convert single dma address to h/w link table format 18 */ 19 static inline void dma_to_sec4_sg_one(struct sec4_sg_entry *sec4_sg_ptr, 20 dma_addr_t dma, u32 len, u16 offset) 21 { 22 sec4_sg_ptr->ptr = cpu_to_caam_dma64(dma); 23 sec4_sg_ptr->len = cpu_to_caam32(len); 24 sec4_sg_ptr->bpid_offset = cpu_to_caam32(offset & SEC4_SG_OFFSET_MASK); 25 #ifdef DEBUG 26 print_hex_dump(KERN_ERR, "sec4_sg_ptr@: ", 27 DUMP_PREFIX_ADDRESS, 16, 4, sec4_sg_ptr, 28 sizeof(struct sec4_sg_entry), 1); 29 #endif 30 } 31 32 /* 33 * convert scatterlist to h/w link table format 34 * but does not have final bit; instead, returns last entry 35 */ 36 static inline struct sec4_sg_entry * 37 sg_to_sec4_sg(struct scatterlist *sg, int sg_count, 38 struct sec4_sg_entry *sec4_sg_ptr, u16 offset) 39 { 40 while (sg_count) { 41 dma_to_sec4_sg_one(sec4_sg_ptr, sg_dma_address(sg), 42 sg_dma_len(sg), offset); 43 sec4_sg_ptr++; 44 sg = sg_next(sg); 45 sg_count--; 46 } 47 return sec4_sg_ptr - 1; 48 } 49 50 /* 51 * convert scatterlist to h/w link table format 52 * scatterlist must have been previously dma mapped 53 */ 54 static inline void sg_to_sec4_sg_last(struct scatterlist *sg, int sg_count, 55 struct sec4_sg_entry *sec4_sg_ptr, 56 u16 offset) 57 { 58 sec4_sg_ptr = sg_to_sec4_sg(sg, sg_count, sec4_sg_ptr, offset); 59 sec4_sg_ptr->len |= cpu_to_caam32(SEC4_SG_LEN_FIN); 60 } 61 62 static inline struct sec4_sg_entry *sg_to_sec4_sg_len( 63 struct scatterlist *sg, unsigned int total, 64 struct sec4_sg_entry *sec4_sg_ptr) 65 { 66 do { 67 unsigned int len = min(sg_dma_len(sg), total); 68 69 dma_to_sec4_sg_one(sec4_sg_ptr, sg_dma_address(sg), len, 0); 70 sec4_sg_ptr++; 71 sg = sg_next(sg); 72 total -= len; 73 } while (total); 74 return sec4_sg_ptr - 1; 75 } 76 77 /* derive number of elements in scatterlist, but return 0 for 1 */ 78 static inline int sg_count(struct scatterlist *sg_list, int nbytes) 79 { 80 int sg_nents = sg_nents_for_len(sg_list, nbytes); 81 82 if (likely(sg_nents == 1)) 83 return 0; 84 85 return sg_nents; 86 } 87