1049359d655277c382683a6030ae0bac485568ffcJames Hsiao/** 2049359d655277c382683a6030ae0bac485568ffcJames Hsiao * AMCC SoC PPC4xx Crypto Driver 3049359d655277c382683a6030ae0bac485568ffcJames Hsiao * 4049359d655277c382683a6030ae0bac485568ffcJames Hsiao * Copyright (c) 2008 Applied Micro Circuits Corporation. 5049359d655277c382683a6030ae0bac485568ffcJames Hsiao * All rights reserved. James Hsiao <jhsiao@amcc.com> 6049359d655277c382683a6030ae0bac485568ffcJames Hsiao * 7049359d655277c382683a6030ae0bac485568ffcJames Hsiao * This program is free software; you can redistribute it and/or modify 8049359d655277c382683a6030ae0bac485568ffcJames Hsiao * it under the terms of the GNU General Public License as published by 9049359d655277c382683a6030ae0bac485568ffcJames Hsiao * the Free Software Foundation; either version 2 of the License, or 10049359d655277c382683a6030ae0bac485568ffcJames Hsiao * (at your option) any later version. 11049359d655277c382683a6030ae0bac485568ffcJames Hsiao * 12049359d655277c382683a6030ae0bac485568ffcJames Hsiao * This program is distributed in the hope that it will be useful, 13049359d655277c382683a6030ae0bac485568ffcJames Hsiao * but WITHOUT ANY WARRANTY; without even the implied warranty of 14049359d655277c382683a6030ae0bac485568ffcJames Hsiao * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15049359d655277c382683a6030ae0bac485568ffcJames Hsiao * GNU General Public License for more details. 16049359d655277c382683a6030ae0bac485568ffcJames Hsiao * 17049359d655277c382683a6030ae0bac485568ffcJames Hsiao * This file implements AMCC crypto offload Linux device driver for use with 18049359d655277c382683a6030ae0bac485568ffcJames Hsiao * Linux CryptoAPI. 19049359d655277c382683a6030ae0bac485568ffcJames Hsiao */ 20049359d655277c382683a6030ae0bac485568ffcJames Hsiao 21049359d655277c382683a6030ae0bac485568ffcJames Hsiao#include <linux/kernel.h> 22049359d655277c382683a6030ae0bac485568ffcJames Hsiao#include <linux/interrupt.h> 23049359d655277c382683a6030ae0bac485568ffcJames Hsiao#include <linux/spinlock_types.h> 24049359d655277c382683a6030ae0bac485568ffcJames Hsiao#include <linux/random.h> 25049359d655277c382683a6030ae0bac485568ffcJames Hsiao#include <linux/scatterlist.h> 26049359d655277c382683a6030ae0bac485568ffcJames Hsiao#include <linux/crypto.h> 27049359d655277c382683a6030ae0bac485568ffcJames Hsiao#include <linux/dma-mapping.h> 28049359d655277c382683a6030ae0bac485568ffcJames Hsiao#include <linux/platform_device.h> 29049359d655277c382683a6030ae0bac485568ffcJames Hsiao#include <linux/init.h> 30c11eede69b6ad0ac44ebc1e021a8d2699c5f1f8fRob Herring#include <linux/module.h> 31c11eede69b6ad0ac44ebc1e021a8d2699c5f1f8fRob Herring#include <linux/of_address.h> 32c11eede69b6ad0ac44ebc1e021a8d2699c5f1f8fRob Herring#include <linux/of_irq.h> 33049359d655277c382683a6030ae0bac485568ffcJames Hsiao#include <linux/of_platform.h> 345a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 35049359d655277c382683a6030ae0bac485568ffcJames Hsiao#include <asm/dcr.h> 36049359d655277c382683a6030ae0bac485568ffcJames Hsiao#include <asm/dcr-regs.h> 37049359d655277c382683a6030ae0bac485568ffcJames Hsiao#include <asm/cacheflush.h> 38049359d655277c382683a6030ae0bac485568ffcJames Hsiao#include <crypto/aes.h> 39049359d655277c382683a6030ae0bac485568ffcJames Hsiao#include <crypto/sha.h> 40049359d655277c382683a6030ae0bac485568ffcJames Hsiao#include "crypto4xx_reg_def.h" 41049359d655277c382683a6030ae0bac485568ffcJames Hsiao#include "crypto4xx_core.h" 42049359d655277c382683a6030ae0bac485568ffcJames Hsiao#include "crypto4xx_sa.h" 43049359d655277c382683a6030ae0bac485568ffcJames Hsiao 44049359d655277c382683a6030ae0bac485568ffcJames Hsiao#define PPC4XX_SEC_VERSION_STR "0.5" 45049359d655277c382683a6030ae0bac485568ffcJames Hsiao 46049359d655277c382683a6030ae0bac485568ffcJames Hsiao/** 47049359d655277c382683a6030ae0bac485568ffcJames Hsiao * PPC4xx Crypto Engine Initialization Routine 48049359d655277c382683a6030ae0bac485568ffcJames Hsiao */ 49049359d655277c382683a6030ae0bac485568ffcJames Hsiaostatic void crypto4xx_hw_init(struct crypto4xx_device *dev) 50049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 51049359d655277c382683a6030ae0bac485568ffcJames Hsiao union ce_ring_size ring_size; 52049359d655277c382683a6030ae0bac485568ffcJames Hsiao union ce_ring_contol ring_ctrl; 53049359d655277c382683a6030ae0bac485568ffcJames Hsiao union ce_part_ring_size part_ring_size; 54049359d655277c382683a6030ae0bac485568ffcJames Hsiao union ce_io_threshold io_threshold; 55049359d655277c382683a6030ae0bac485568ffcJames Hsiao u32 rand_num; 56049359d655277c382683a6030ae0bac485568ffcJames Hsiao union ce_pe_dma_cfg pe_dma_cfg; 57c5697462ae94693764e468b701c616bbbd6f951cJosh Boyer u32 device_ctrl; 58049359d655277c382683a6030ae0bac485568ffcJames Hsiao 59049359d655277c382683a6030ae0bac485568ffcJames Hsiao writel(PPC4XX_BYTE_ORDER, dev->ce_base + CRYPTO4XX_BYTE_ORDER_CFG); 60049359d655277c382683a6030ae0bac485568ffcJames Hsiao /* setup pe dma, include reset sg, pdr and pe, then release reset */ 61049359d655277c382683a6030ae0bac485568ffcJames Hsiao pe_dma_cfg.w = 0; 62049359d655277c382683a6030ae0bac485568ffcJames Hsiao pe_dma_cfg.bf.bo_sgpd_en = 1; 63049359d655277c382683a6030ae0bac485568ffcJames Hsiao pe_dma_cfg.bf.bo_data_en = 0; 64049359d655277c382683a6030ae0bac485568ffcJames Hsiao pe_dma_cfg.bf.bo_sa_en = 1; 65049359d655277c382683a6030ae0bac485568ffcJames Hsiao pe_dma_cfg.bf.bo_pd_en = 1; 66049359d655277c382683a6030ae0bac485568ffcJames Hsiao pe_dma_cfg.bf.dynamic_sa_en = 1; 67049359d655277c382683a6030ae0bac485568ffcJames Hsiao pe_dma_cfg.bf.reset_sg = 1; 68049359d655277c382683a6030ae0bac485568ffcJames Hsiao pe_dma_cfg.bf.reset_pdr = 1; 69049359d655277c382683a6030ae0bac485568ffcJames Hsiao pe_dma_cfg.bf.reset_pe = 1; 70049359d655277c382683a6030ae0bac485568ffcJames Hsiao writel(pe_dma_cfg.w, dev->ce_base + CRYPTO4XX_PE_DMA_CFG); 71049359d655277c382683a6030ae0bac485568ffcJames Hsiao /* un reset pe,sg and pdr */ 72049359d655277c382683a6030ae0bac485568ffcJames Hsiao pe_dma_cfg.bf.pe_mode = 0; 73049359d655277c382683a6030ae0bac485568ffcJames Hsiao pe_dma_cfg.bf.reset_sg = 0; 74049359d655277c382683a6030ae0bac485568ffcJames Hsiao pe_dma_cfg.bf.reset_pdr = 0; 75049359d655277c382683a6030ae0bac485568ffcJames Hsiao pe_dma_cfg.bf.reset_pe = 0; 76049359d655277c382683a6030ae0bac485568ffcJames Hsiao pe_dma_cfg.bf.bo_td_en = 0; 77049359d655277c382683a6030ae0bac485568ffcJames Hsiao writel(pe_dma_cfg.w, dev->ce_base + CRYPTO4XX_PE_DMA_CFG); 78049359d655277c382683a6030ae0bac485568ffcJames Hsiao writel(dev->pdr_pa, dev->ce_base + CRYPTO4XX_PDR_BASE); 79049359d655277c382683a6030ae0bac485568ffcJames Hsiao writel(dev->pdr_pa, dev->ce_base + CRYPTO4XX_RDR_BASE); 80049359d655277c382683a6030ae0bac485568ffcJames Hsiao writel(PPC4XX_PRNG_CTRL_AUTO_EN, dev->ce_base + CRYPTO4XX_PRNG_CTRL); 81049359d655277c382683a6030ae0bac485568ffcJames Hsiao get_random_bytes(&rand_num, sizeof(rand_num)); 82049359d655277c382683a6030ae0bac485568ffcJames Hsiao writel(rand_num, dev->ce_base + CRYPTO4XX_PRNG_SEED_L); 83049359d655277c382683a6030ae0bac485568ffcJames Hsiao get_random_bytes(&rand_num, sizeof(rand_num)); 84049359d655277c382683a6030ae0bac485568ffcJames Hsiao writel(rand_num, dev->ce_base + CRYPTO4XX_PRNG_SEED_H); 85049359d655277c382683a6030ae0bac485568ffcJames Hsiao ring_size.w = 0; 86049359d655277c382683a6030ae0bac485568ffcJames Hsiao ring_size.bf.ring_offset = PPC4XX_PD_SIZE; 87049359d655277c382683a6030ae0bac485568ffcJames Hsiao ring_size.bf.ring_size = PPC4XX_NUM_PD; 88049359d655277c382683a6030ae0bac485568ffcJames Hsiao writel(ring_size.w, dev->ce_base + CRYPTO4XX_RING_SIZE); 89049359d655277c382683a6030ae0bac485568ffcJames Hsiao ring_ctrl.w = 0; 90049359d655277c382683a6030ae0bac485568ffcJames Hsiao writel(ring_ctrl.w, dev->ce_base + CRYPTO4XX_RING_CTRL); 91c5697462ae94693764e468b701c616bbbd6f951cJosh Boyer device_ctrl = readl(dev->ce_base + CRYPTO4XX_DEVICE_CTRL); 92c5697462ae94693764e468b701c616bbbd6f951cJosh Boyer device_ctrl |= PPC4XX_DC_3DES_EN; 93c5697462ae94693764e468b701c616bbbd6f951cJosh Boyer writel(device_ctrl, dev->ce_base + CRYPTO4XX_DEVICE_CTRL); 94049359d655277c382683a6030ae0bac485568ffcJames Hsiao writel(dev->gdr_pa, dev->ce_base + CRYPTO4XX_GATH_RING_BASE); 95049359d655277c382683a6030ae0bac485568ffcJames Hsiao writel(dev->sdr_pa, dev->ce_base + CRYPTO4XX_SCAT_RING_BASE); 96049359d655277c382683a6030ae0bac485568ffcJames Hsiao part_ring_size.w = 0; 97049359d655277c382683a6030ae0bac485568ffcJames Hsiao part_ring_size.bf.sdr_size = PPC4XX_SDR_SIZE; 98049359d655277c382683a6030ae0bac485568ffcJames Hsiao part_ring_size.bf.gdr_size = PPC4XX_GDR_SIZE; 99049359d655277c382683a6030ae0bac485568ffcJames Hsiao writel(part_ring_size.w, dev->ce_base + CRYPTO4XX_PART_RING_SIZE); 100049359d655277c382683a6030ae0bac485568ffcJames Hsiao writel(PPC4XX_SD_BUFFER_SIZE, dev->ce_base + CRYPTO4XX_PART_RING_CFG); 101049359d655277c382683a6030ae0bac485568ffcJames Hsiao io_threshold.w = 0; 102049359d655277c382683a6030ae0bac485568ffcJames Hsiao io_threshold.bf.output_threshold = PPC4XX_OUTPUT_THRESHOLD; 103049359d655277c382683a6030ae0bac485568ffcJames Hsiao io_threshold.bf.input_threshold = PPC4XX_INPUT_THRESHOLD; 104049359d655277c382683a6030ae0bac485568ffcJames Hsiao writel(io_threshold.w, dev->ce_base + CRYPTO4XX_IO_THRESHOLD); 105049359d655277c382683a6030ae0bac485568ffcJames Hsiao writel(0, dev->ce_base + CRYPTO4XX_PDR_BASE_UADDR); 106049359d655277c382683a6030ae0bac485568ffcJames Hsiao writel(0, dev->ce_base + CRYPTO4XX_RDR_BASE_UADDR); 107049359d655277c382683a6030ae0bac485568ffcJames Hsiao writel(0, dev->ce_base + CRYPTO4XX_PKT_SRC_UADDR); 108049359d655277c382683a6030ae0bac485568ffcJames Hsiao writel(0, dev->ce_base + CRYPTO4XX_PKT_DEST_UADDR); 109049359d655277c382683a6030ae0bac485568ffcJames Hsiao writel(0, dev->ce_base + CRYPTO4XX_SA_UADDR); 110049359d655277c382683a6030ae0bac485568ffcJames Hsiao writel(0, dev->ce_base + CRYPTO4XX_GATH_RING_BASE_UADDR); 111049359d655277c382683a6030ae0bac485568ffcJames Hsiao writel(0, dev->ce_base + CRYPTO4XX_SCAT_RING_BASE_UADDR); 112049359d655277c382683a6030ae0bac485568ffcJames Hsiao /* un reset pe,sg and pdr */ 113049359d655277c382683a6030ae0bac485568ffcJames Hsiao pe_dma_cfg.bf.pe_mode = 1; 114049359d655277c382683a6030ae0bac485568ffcJames Hsiao pe_dma_cfg.bf.reset_sg = 0; 115049359d655277c382683a6030ae0bac485568ffcJames Hsiao pe_dma_cfg.bf.reset_pdr = 0; 116049359d655277c382683a6030ae0bac485568ffcJames Hsiao pe_dma_cfg.bf.reset_pe = 0; 117049359d655277c382683a6030ae0bac485568ffcJames Hsiao pe_dma_cfg.bf.bo_td_en = 0; 118049359d655277c382683a6030ae0bac485568ffcJames Hsiao writel(pe_dma_cfg.w, dev->ce_base + CRYPTO4XX_PE_DMA_CFG); 119049359d655277c382683a6030ae0bac485568ffcJames Hsiao /*clear all pending interrupt*/ 120049359d655277c382683a6030ae0bac485568ffcJames Hsiao writel(PPC4XX_INTERRUPT_CLR, dev->ce_base + CRYPTO4XX_INT_CLR); 121049359d655277c382683a6030ae0bac485568ffcJames Hsiao writel(PPC4XX_INT_DESCR_CNT, dev->ce_base + CRYPTO4XX_INT_DESCR_CNT); 122049359d655277c382683a6030ae0bac485568ffcJames Hsiao writel(PPC4XX_INT_DESCR_CNT, dev->ce_base + CRYPTO4XX_INT_DESCR_CNT); 123049359d655277c382683a6030ae0bac485568ffcJames Hsiao writel(PPC4XX_INT_CFG, dev->ce_base + CRYPTO4XX_INT_CFG); 124049359d655277c382683a6030ae0bac485568ffcJames Hsiao writel(PPC4XX_PD_DONE_INT, dev->ce_base + CRYPTO4XX_INT_EN); 125049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 126049359d655277c382683a6030ae0bac485568ffcJames Hsiao 127049359d655277c382683a6030ae0bac485568ffcJames Hsiaoint crypto4xx_alloc_sa(struct crypto4xx_ctx *ctx, u32 size) 128049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 129049359d655277c382683a6030ae0bac485568ffcJames Hsiao ctx->sa_in = dma_alloc_coherent(ctx->dev->core_dev->device, size * 4, 130049359d655277c382683a6030ae0bac485568ffcJames Hsiao &ctx->sa_in_dma_addr, GFP_ATOMIC); 131049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (ctx->sa_in == NULL) 132049359d655277c382683a6030ae0bac485568ffcJames Hsiao return -ENOMEM; 133049359d655277c382683a6030ae0bac485568ffcJames Hsiao 134049359d655277c382683a6030ae0bac485568ffcJames Hsiao ctx->sa_out = dma_alloc_coherent(ctx->dev->core_dev->device, size * 4, 135049359d655277c382683a6030ae0bac485568ffcJames Hsiao &ctx->sa_out_dma_addr, GFP_ATOMIC); 136049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (ctx->sa_out == NULL) { 137049359d655277c382683a6030ae0bac485568ffcJames Hsiao dma_free_coherent(ctx->dev->core_dev->device, 138049359d655277c382683a6030ae0bac485568ffcJames Hsiao ctx->sa_len * 4, 139049359d655277c382683a6030ae0bac485568ffcJames Hsiao ctx->sa_in, ctx->sa_in_dma_addr); 140049359d655277c382683a6030ae0bac485568ffcJames Hsiao return -ENOMEM; 141049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 142049359d655277c382683a6030ae0bac485568ffcJames Hsiao 143049359d655277c382683a6030ae0bac485568ffcJames Hsiao memset(ctx->sa_in, 0, size * 4); 144049359d655277c382683a6030ae0bac485568ffcJames Hsiao memset(ctx->sa_out, 0, size * 4); 145049359d655277c382683a6030ae0bac485568ffcJames Hsiao ctx->sa_len = size; 146049359d655277c382683a6030ae0bac485568ffcJames Hsiao 147049359d655277c382683a6030ae0bac485568ffcJames Hsiao return 0; 148049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 149049359d655277c382683a6030ae0bac485568ffcJames Hsiao 150049359d655277c382683a6030ae0bac485568ffcJames Hsiaovoid crypto4xx_free_sa(struct crypto4xx_ctx *ctx) 151049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 152049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (ctx->sa_in != NULL) 153049359d655277c382683a6030ae0bac485568ffcJames Hsiao dma_free_coherent(ctx->dev->core_dev->device, ctx->sa_len * 4, 154049359d655277c382683a6030ae0bac485568ffcJames Hsiao ctx->sa_in, ctx->sa_in_dma_addr); 155049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (ctx->sa_out != NULL) 156049359d655277c382683a6030ae0bac485568ffcJames Hsiao dma_free_coherent(ctx->dev->core_dev->device, ctx->sa_len * 4, 157049359d655277c382683a6030ae0bac485568ffcJames Hsiao ctx->sa_out, ctx->sa_out_dma_addr); 158049359d655277c382683a6030ae0bac485568ffcJames Hsiao 159049359d655277c382683a6030ae0bac485568ffcJames Hsiao ctx->sa_in_dma_addr = 0; 160049359d655277c382683a6030ae0bac485568ffcJames Hsiao ctx->sa_out_dma_addr = 0; 161049359d655277c382683a6030ae0bac485568ffcJames Hsiao ctx->sa_len = 0; 162049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 163049359d655277c382683a6030ae0bac485568ffcJames Hsiao 164049359d655277c382683a6030ae0bac485568ffcJames Hsiaou32 crypto4xx_alloc_state_record(struct crypto4xx_ctx *ctx) 165049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 166049359d655277c382683a6030ae0bac485568ffcJames Hsiao ctx->state_record = dma_alloc_coherent(ctx->dev->core_dev->device, 167049359d655277c382683a6030ae0bac485568ffcJames Hsiao sizeof(struct sa_state_record), 168049359d655277c382683a6030ae0bac485568ffcJames Hsiao &ctx->state_record_dma_addr, GFP_ATOMIC); 169049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (!ctx->state_record_dma_addr) 170049359d655277c382683a6030ae0bac485568ffcJames Hsiao return -ENOMEM; 171049359d655277c382683a6030ae0bac485568ffcJames Hsiao memset(ctx->state_record, 0, sizeof(struct sa_state_record)); 172049359d655277c382683a6030ae0bac485568ffcJames Hsiao 173049359d655277c382683a6030ae0bac485568ffcJames Hsiao return 0; 174049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 175049359d655277c382683a6030ae0bac485568ffcJames Hsiao 176049359d655277c382683a6030ae0bac485568ffcJames Hsiaovoid crypto4xx_free_state_record(struct crypto4xx_ctx *ctx) 177049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 178049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (ctx->state_record != NULL) 179049359d655277c382683a6030ae0bac485568ffcJames Hsiao dma_free_coherent(ctx->dev->core_dev->device, 180049359d655277c382683a6030ae0bac485568ffcJames Hsiao sizeof(struct sa_state_record), 181049359d655277c382683a6030ae0bac485568ffcJames Hsiao ctx->state_record, 182049359d655277c382683a6030ae0bac485568ffcJames Hsiao ctx->state_record_dma_addr); 183049359d655277c382683a6030ae0bac485568ffcJames Hsiao ctx->state_record_dma_addr = 0; 184049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 185049359d655277c382683a6030ae0bac485568ffcJames Hsiao 186049359d655277c382683a6030ae0bac485568ffcJames Hsiao/** 187049359d655277c382683a6030ae0bac485568ffcJames Hsiao * alloc memory for the gather ring 188049359d655277c382683a6030ae0bac485568ffcJames Hsiao * no need to alloc buf for the ring 189049359d655277c382683a6030ae0bac485568ffcJames Hsiao * gdr_tail, gdr_head and gdr_count are initialized by this function 190049359d655277c382683a6030ae0bac485568ffcJames Hsiao */ 191049359d655277c382683a6030ae0bac485568ffcJames Hsiaostatic u32 crypto4xx_build_pdr(struct crypto4xx_device *dev) 192049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 193049359d655277c382683a6030ae0bac485568ffcJames Hsiao int i; 194049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct pd_uinfo *pd_uinfo; 195049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->pdr = dma_alloc_coherent(dev->core_dev->device, 196049359d655277c382683a6030ae0bac485568ffcJames Hsiao sizeof(struct ce_pd) * PPC4XX_NUM_PD, 197049359d655277c382683a6030ae0bac485568ffcJames Hsiao &dev->pdr_pa, GFP_ATOMIC); 198049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (!dev->pdr) 199049359d655277c382683a6030ae0bac485568ffcJames Hsiao return -ENOMEM; 200049359d655277c382683a6030ae0bac485568ffcJames Hsiao 201049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->pdr_uinfo = kzalloc(sizeof(struct pd_uinfo) * PPC4XX_NUM_PD, 202049359d655277c382683a6030ae0bac485568ffcJames Hsiao GFP_KERNEL); 203049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (!dev->pdr_uinfo) { 204049359d655277c382683a6030ae0bac485568ffcJames Hsiao dma_free_coherent(dev->core_dev->device, 205049359d655277c382683a6030ae0bac485568ffcJames Hsiao sizeof(struct ce_pd) * PPC4XX_NUM_PD, 206049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->pdr, 207049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->pdr_pa); 208049359d655277c382683a6030ae0bac485568ffcJames Hsiao return -ENOMEM; 209049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 210049359d655277c382683a6030ae0bac485568ffcJames Hsiao memset(dev->pdr, 0, sizeof(struct ce_pd) * PPC4XX_NUM_PD); 211049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->shadow_sa_pool = dma_alloc_coherent(dev->core_dev->device, 212049359d655277c382683a6030ae0bac485568ffcJames Hsiao 256 * PPC4XX_NUM_PD, 213049359d655277c382683a6030ae0bac485568ffcJames Hsiao &dev->shadow_sa_pool_pa, 214049359d655277c382683a6030ae0bac485568ffcJames Hsiao GFP_ATOMIC); 215049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (!dev->shadow_sa_pool) 216049359d655277c382683a6030ae0bac485568ffcJames Hsiao return -ENOMEM; 217049359d655277c382683a6030ae0bac485568ffcJames Hsiao 218049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->shadow_sr_pool = dma_alloc_coherent(dev->core_dev->device, 219049359d655277c382683a6030ae0bac485568ffcJames Hsiao sizeof(struct sa_state_record) * PPC4XX_NUM_PD, 220049359d655277c382683a6030ae0bac485568ffcJames Hsiao &dev->shadow_sr_pool_pa, GFP_ATOMIC); 221049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (!dev->shadow_sr_pool) 222049359d655277c382683a6030ae0bac485568ffcJames Hsiao return -ENOMEM; 223049359d655277c382683a6030ae0bac485568ffcJames Hsiao for (i = 0; i < PPC4XX_NUM_PD; i++) { 224049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd_uinfo = (struct pd_uinfo *) (dev->pdr_uinfo + 225049359d655277c382683a6030ae0bac485568ffcJames Hsiao sizeof(struct pd_uinfo) * i); 226049359d655277c382683a6030ae0bac485568ffcJames Hsiao 227049359d655277c382683a6030ae0bac485568ffcJames Hsiao /* alloc 256 bytes which is enough for any kind of dynamic sa */ 228049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd_uinfo->sa_va = dev->shadow_sa_pool + 256 * i; 229049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd_uinfo->sa_pa = dev->shadow_sa_pool_pa + 256 * i; 230049359d655277c382683a6030ae0bac485568ffcJames Hsiao 231049359d655277c382683a6030ae0bac485568ffcJames Hsiao /* alloc state record */ 232049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd_uinfo->sr_va = dev->shadow_sr_pool + 233049359d655277c382683a6030ae0bac485568ffcJames Hsiao sizeof(struct sa_state_record) * i; 234049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd_uinfo->sr_pa = dev->shadow_sr_pool_pa + 235049359d655277c382683a6030ae0bac485568ffcJames Hsiao sizeof(struct sa_state_record) * i; 236049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 237049359d655277c382683a6030ae0bac485568ffcJames Hsiao 238049359d655277c382683a6030ae0bac485568ffcJames Hsiao return 0; 239049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 240049359d655277c382683a6030ae0bac485568ffcJames Hsiao 241049359d655277c382683a6030ae0bac485568ffcJames Hsiaostatic void crypto4xx_destroy_pdr(struct crypto4xx_device *dev) 242049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 243049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (dev->pdr != NULL) 244049359d655277c382683a6030ae0bac485568ffcJames Hsiao dma_free_coherent(dev->core_dev->device, 245049359d655277c382683a6030ae0bac485568ffcJames Hsiao sizeof(struct ce_pd) * PPC4XX_NUM_PD, 246049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->pdr, dev->pdr_pa); 247049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (dev->shadow_sa_pool) 248049359d655277c382683a6030ae0bac485568ffcJames Hsiao dma_free_coherent(dev->core_dev->device, 256 * PPC4XX_NUM_PD, 249049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->shadow_sa_pool, dev->shadow_sa_pool_pa); 250049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (dev->shadow_sr_pool) 251049359d655277c382683a6030ae0bac485568ffcJames Hsiao dma_free_coherent(dev->core_dev->device, 252049359d655277c382683a6030ae0bac485568ffcJames Hsiao sizeof(struct sa_state_record) * PPC4XX_NUM_PD, 253049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->shadow_sr_pool, dev->shadow_sr_pool_pa); 254049359d655277c382683a6030ae0bac485568ffcJames Hsiao 255049359d655277c382683a6030ae0bac485568ffcJames Hsiao kfree(dev->pdr_uinfo); 256049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 257049359d655277c382683a6030ae0bac485568ffcJames Hsiao 258049359d655277c382683a6030ae0bac485568ffcJames Hsiaostatic u32 crypto4xx_get_pd_from_pdr_nolock(struct crypto4xx_device *dev) 259049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 260049359d655277c382683a6030ae0bac485568ffcJames Hsiao u32 retval; 261049359d655277c382683a6030ae0bac485568ffcJames Hsiao u32 tmp; 262049359d655277c382683a6030ae0bac485568ffcJames Hsiao 263049359d655277c382683a6030ae0bac485568ffcJames Hsiao retval = dev->pdr_head; 264049359d655277c382683a6030ae0bac485568ffcJames Hsiao tmp = (dev->pdr_head + 1) % PPC4XX_NUM_PD; 265049359d655277c382683a6030ae0bac485568ffcJames Hsiao 266049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (tmp == dev->pdr_tail) 267049359d655277c382683a6030ae0bac485568ffcJames Hsiao return ERING_WAS_FULL; 268049359d655277c382683a6030ae0bac485568ffcJames Hsiao 269049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->pdr_head = tmp; 270049359d655277c382683a6030ae0bac485568ffcJames Hsiao 271049359d655277c382683a6030ae0bac485568ffcJames Hsiao return retval; 272049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 273049359d655277c382683a6030ae0bac485568ffcJames Hsiao 274049359d655277c382683a6030ae0bac485568ffcJames Hsiaostatic u32 crypto4xx_put_pd_to_pdr(struct crypto4xx_device *dev, u32 idx) 275049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 276049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct pd_uinfo *pd_uinfo; 277049359d655277c382683a6030ae0bac485568ffcJames Hsiao unsigned long flags; 278049359d655277c382683a6030ae0bac485568ffcJames Hsiao 279049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd_uinfo = (struct pd_uinfo *)(dev->pdr_uinfo + 280049359d655277c382683a6030ae0bac485568ffcJames Hsiao sizeof(struct pd_uinfo) * idx); 281049359d655277c382683a6030ae0bac485568ffcJames Hsiao spin_lock_irqsave(&dev->core_dev->lock, flags); 282049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (dev->pdr_tail != PPC4XX_LAST_PD) 283049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->pdr_tail++; 284049359d655277c382683a6030ae0bac485568ffcJames Hsiao else 285049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->pdr_tail = 0; 286049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd_uinfo->state = PD_ENTRY_FREE; 287049359d655277c382683a6030ae0bac485568ffcJames Hsiao spin_unlock_irqrestore(&dev->core_dev->lock, flags); 288049359d655277c382683a6030ae0bac485568ffcJames Hsiao 289049359d655277c382683a6030ae0bac485568ffcJames Hsiao return 0; 290049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 291049359d655277c382683a6030ae0bac485568ffcJames Hsiao 292049359d655277c382683a6030ae0bac485568ffcJames Hsiaostatic struct ce_pd *crypto4xx_get_pdp(struct crypto4xx_device *dev, 293049359d655277c382683a6030ae0bac485568ffcJames Hsiao dma_addr_t *pd_dma, u32 idx) 294049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 295049359d655277c382683a6030ae0bac485568ffcJames Hsiao *pd_dma = dev->pdr_pa + sizeof(struct ce_pd) * idx; 296049359d655277c382683a6030ae0bac485568ffcJames Hsiao 297049359d655277c382683a6030ae0bac485568ffcJames Hsiao return dev->pdr + sizeof(struct ce_pd) * idx; 298049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 299049359d655277c382683a6030ae0bac485568ffcJames Hsiao 300049359d655277c382683a6030ae0bac485568ffcJames Hsiao/** 301049359d655277c382683a6030ae0bac485568ffcJames Hsiao * alloc memory for the gather ring 302049359d655277c382683a6030ae0bac485568ffcJames Hsiao * no need to alloc buf for the ring 303049359d655277c382683a6030ae0bac485568ffcJames Hsiao * gdr_tail, gdr_head and gdr_count are initialized by this function 304049359d655277c382683a6030ae0bac485568ffcJames Hsiao */ 305049359d655277c382683a6030ae0bac485568ffcJames Hsiaostatic u32 crypto4xx_build_gdr(struct crypto4xx_device *dev) 306049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 307049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->gdr = dma_alloc_coherent(dev->core_dev->device, 308049359d655277c382683a6030ae0bac485568ffcJames Hsiao sizeof(struct ce_gd) * PPC4XX_NUM_GD, 309049359d655277c382683a6030ae0bac485568ffcJames Hsiao &dev->gdr_pa, GFP_ATOMIC); 310049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (!dev->gdr) 311049359d655277c382683a6030ae0bac485568ffcJames Hsiao return -ENOMEM; 312049359d655277c382683a6030ae0bac485568ffcJames Hsiao 313049359d655277c382683a6030ae0bac485568ffcJames Hsiao memset(dev->gdr, 0, sizeof(struct ce_gd) * PPC4XX_NUM_GD); 314049359d655277c382683a6030ae0bac485568ffcJames Hsiao 315049359d655277c382683a6030ae0bac485568ffcJames Hsiao return 0; 316049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 317049359d655277c382683a6030ae0bac485568ffcJames Hsiao 318049359d655277c382683a6030ae0bac485568ffcJames Hsiaostatic inline void crypto4xx_destroy_gdr(struct crypto4xx_device *dev) 319049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 320049359d655277c382683a6030ae0bac485568ffcJames Hsiao dma_free_coherent(dev->core_dev->device, 321049359d655277c382683a6030ae0bac485568ffcJames Hsiao sizeof(struct ce_gd) * PPC4XX_NUM_GD, 322049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->gdr, dev->gdr_pa); 323049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 324049359d655277c382683a6030ae0bac485568ffcJames Hsiao 325049359d655277c382683a6030ae0bac485568ffcJames Hsiao/* 326049359d655277c382683a6030ae0bac485568ffcJames Hsiao * when this function is called. 327049359d655277c382683a6030ae0bac485568ffcJames Hsiao * preemption or interrupt must be disabled 328049359d655277c382683a6030ae0bac485568ffcJames Hsiao */ 329049359d655277c382683a6030ae0bac485568ffcJames Hsiaou32 crypto4xx_get_n_gd(struct crypto4xx_device *dev, int n) 330049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 331049359d655277c382683a6030ae0bac485568ffcJames Hsiao u32 retval; 332049359d655277c382683a6030ae0bac485568ffcJames Hsiao u32 tmp; 333049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (n >= PPC4XX_NUM_GD) 334049359d655277c382683a6030ae0bac485568ffcJames Hsiao return ERING_WAS_FULL; 335049359d655277c382683a6030ae0bac485568ffcJames Hsiao 336049359d655277c382683a6030ae0bac485568ffcJames Hsiao retval = dev->gdr_head; 337049359d655277c382683a6030ae0bac485568ffcJames Hsiao tmp = (dev->gdr_head + n) % PPC4XX_NUM_GD; 338049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (dev->gdr_head > dev->gdr_tail) { 339049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (tmp < dev->gdr_head && tmp >= dev->gdr_tail) 340049359d655277c382683a6030ae0bac485568ffcJames Hsiao return ERING_WAS_FULL; 341049359d655277c382683a6030ae0bac485568ffcJames Hsiao } else if (dev->gdr_head < dev->gdr_tail) { 342049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (tmp < dev->gdr_head || tmp >= dev->gdr_tail) 343049359d655277c382683a6030ae0bac485568ffcJames Hsiao return ERING_WAS_FULL; 344049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 345049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->gdr_head = tmp; 346049359d655277c382683a6030ae0bac485568ffcJames Hsiao 347049359d655277c382683a6030ae0bac485568ffcJames Hsiao return retval; 348049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 349049359d655277c382683a6030ae0bac485568ffcJames Hsiao 350049359d655277c382683a6030ae0bac485568ffcJames Hsiaostatic u32 crypto4xx_put_gd_to_gdr(struct crypto4xx_device *dev) 351049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 352049359d655277c382683a6030ae0bac485568ffcJames Hsiao unsigned long flags; 353049359d655277c382683a6030ae0bac485568ffcJames Hsiao 354049359d655277c382683a6030ae0bac485568ffcJames Hsiao spin_lock_irqsave(&dev->core_dev->lock, flags); 355049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (dev->gdr_tail == dev->gdr_head) { 356049359d655277c382683a6030ae0bac485568ffcJames Hsiao spin_unlock_irqrestore(&dev->core_dev->lock, flags); 357049359d655277c382683a6030ae0bac485568ffcJames Hsiao return 0; 358049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 359049359d655277c382683a6030ae0bac485568ffcJames Hsiao 360049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (dev->gdr_tail != PPC4XX_LAST_GD) 361049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->gdr_tail++; 362049359d655277c382683a6030ae0bac485568ffcJames Hsiao else 363049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->gdr_tail = 0; 364049359d655277c382683a6030ae0bac485568ffcJames Hsiao 365049359d655277c382683a6030ae0bac485568ffcJames Hsiao spin_unlock_irqrestore(&dev->core_dev->lock, flags); 366049359d655277c382683a6030ae0bac485568ffcJames Hsiao 367049359d655277c382683a6030ae0bac485568ffcJames Hsiao return 0; 368049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 369049359d655277c382683a6030ae0bac485568ffcJames Hsiao 370049359d655277c382683a6030ae0bac485568ffcJames Hsiaostatic inline struct ce_gd *crypto4xx_get_gdp(struct crypto4xx_device *dev, 371049359d655277c382683a6030ae0bac485568ffcJames Hsiao dma_addr_t *gd_dma, u32 idx) 372049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 373049359d655277c382683a6030ae0bac485568ffcJames Hsiao *gd_dma = dev->gdr_pa + sizeof(struct ce_gd) * idx; 374049359d655277c382683a6030ae0bac485568ffcJames Hsiao 375049359d655277c382683a6030ae0bac485568ffcJames Hsiao return (struct ce_gd *) (dev->gdr + sizeof(struct ce_gd) * idx); 376049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 377049359d655277c382683a6030ae0bac485568ffcJames Hsiao 378049359d655277c382683a6030ae0bac485568ffcJames Hsiao/** 379049359d655277c382683a6030ae0bac485568ffcJames Hsiao * alloc memory for the scatter ring 380049359d655277c382683a6030ae0bac485568ffcJames Hsiao * need to alloc buf for the ring 381049359d655277c382683a6030ae0bac485568ffcJames Hsiao * sdr_tail, sdr_head and sdr_count are initialized by this function 382049359d655277c382683a6030ae0bac485568ffcJames Hsiao */ 383049359d655277c382683a6030ae0bac485568ffcJames Hsiaostatic u32 crypto4xx_build_sdr(struct crypto4xx_device *dev) 384049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 385049359d655277c382683a6030ae0bac485568ffcJames Hsiao int i; 386049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct ce_sd *sd_array; 387049359d655277c382683a6030ae0bac485568ffcJames Hsiao 388049359d655277c382683a6030ae0bac485568ffcJames Hsiao /* alloc memory for scatter descriptor ring */ 389049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->sdr = dma_alloc_coherent(dev->core_dev->device, 390049359d655277c382683a6030ae0bac485568ffcJames Hsiao sizeof(struct ce_sd) * PPC4XX_NUM_SD, 391049359d655277c382683a6030ae0bac485568ffcJames Hsiao &dev->sdr_pa, GFP_ATOMIC); 392049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (!dev->sdr) 393049359d655277c382683a6030ae0bac485568ffcJames Hsiao return -ENOMEM; 394049359d655277c382683a6030ae0bac485568ffcJames Hsiao 395049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->scatter_buffer_size = PPC4XX_SD_BUFFER_SIZE; 396049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->scatter_buffer_va = 397049359d655277c382683a6030ae0bac485568ffcJames Hsiao dma_alloc_coherent(dev->core_dev->device, 398049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->scatter_buffer_size * PPC4XX_NUM_SD, 399049359d655277c382683a6030ae0bac485568ffcJames Hsiao &dev->scatter_buffer_pa, GFP_ATOMIC); 400049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (!dev->scatter_buffer_va) { 401049359d655277c382683a6030ae0bac485568ffcJames Hsiao dma_free_coherent(dev->core_dev->device, 402049359d655277c382683a6030ae0bac485568ffcJames Hsiao sizeof(struct ce_sd) * PPC4XX_NUM_SD, 403049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->sdr, dev->sdr_pa); 404049359d655277c382683a6030ae0bac485568ffcJames Hsiao return -ENOMEM; 405049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 406049359d655277c382683a6030ae0bac485568ffcJames Hsiao 407049359d655277c382683a6030ae0bac485568ffcJames Hsiao sd_array = dev->sdr; 408049359d655277c382683a6030ae0bac485568ffcJames Hsiao 409049359d655277c382683a6030ae0bac485568ffcJames Hsiao for (i = 0; i < PPC4XX_NUM_SD; i++) { 410049359d655277c382683a6030ae0bac485568ffcJames Hsiao sd_array[i].ptr = dev->scatter_buffer_pa + 411049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->scatter_buffer_size * i; 412049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 413049359d655277c382683a6030ae0bac485568ffcJames Hsiao 414049359d655277c382683a6030ae0bac485568ffcJames Hsiao return 0; 415049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 416049359d655277c382683a6030ae0bac485568ffcJames Hsiao 417049359d655277c382683a6030ae0bac485568ffcJames Hsiaostatic void crypto4xx_destroy_sdr(struct crypto4xx_device *dev) 418049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 419049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (dev->sdr != NULL) 420049359d655277c382683a6030ae0bac485568ffcJames Hsiao dma_free_coherent(dev->core_dev->device, 421049359d655277c382683a6030ae0bac485568ffcJames Hsiao sizeof(struct ce_sd) * PPC4XX_NUM_SD, 422049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->sdr, dev->sdr_pa); 423049359d655277c382683a6030ae0bac485568ffcJames Hsiao 424049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (dev->scatter_buffer_va != NULL) 425049359d655277c382683a6030ae0bac485568ffcJames Hsiao dma_free_coherent(dev->core_dev->device, 426049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->scatter_buffer_size * PPC4XX_NUM_SD, 427049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->scatter_buffer_va, 428049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->scatter_buffer_pa); 429049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 430049359d655277c382683a6030ae0bac485568ffcJames Hsiao 431049359d655277c382683a6030ae0bac485568ffcJames Hsiao/* 432049359d655277c382683a6030ae0bac485568ffcJames Hsiao * when this function is called. 433049359d655277c382683a6030ae0bac485568ffcJames Hsiao * preemption or interrupt must be disabled 434049359d655277c382683a6030ae0bac485568ffcJames Hsiao */ 435049359d655277c382683a6030ae0bac485568ffcJames Hsiaostatic u32 crypto4xx_get_n_sd(struct crypto4xx_device *dev, int n) 436049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 437049359d655277c382683a6030ae0bac485568ffcJames Hsiao u32 retval; 438049359d655277c382683a6030ae0bac485568ffcJames Hsiao u32 tmp; 439049359d655277c382683a6030ae0bac485568ffcJames Hsiao 440049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (n >= PPC4XX_NUM_SD) 441049359d655277c382683a6030ae0bac485568ffcJames Hsiao return ERING_WAS_FULL; 442049359d655277c382683a6030ae0bac485568ffcJames Hsiao 443049359d655277c382683a6030ae0bac485568ffcJames Hsiao retval = dev->sdr_head; 444049359d655277c382683a6030ae0bac485568ffcJames Hsiao tmp = (dev->sdr_head + n) % PPC4XX_NUM_SD; 445049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (dev->sdr_head > dev->gdr_tail) { 446049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (tmp < dev->sdr_head && tmp >= dev->sdr_tail) 447049359d655277c382683a6030ae0bac485568ffcJames Hsiao return ERING_WAS_FULL; 448049359d655277c382683a6030ae0bac485568ffcJames Hsiao } else if (dev->sdr_head < dev->sdr_tail) { 449049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (tmp < dev->sdr_head || tmp >= dev->sdr_tail) 450049359d655277c382683a6030ae0bac485568ffcJames Hsiao return ERING_WAS_FULL; 451049359d655277c382683a6030ae0bac485568ffcJames Hsiao } /* the head = tail, or empty case is already take cared */ 452049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->sdr_head = tmp; 453049359d655277c382683a6030ae0bac485568ffcJames Hsiao 454049359d655277c382683a6030ae0bac485568ffcJames Hsiao return retval; 455049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 456049359d655277c382683a6030ae0bac485568ffcJames Hsiao 457049359d655277c382683a6030ae0bac485568ffcJames Hsiaostatic u32 crypto4xx_put_sd_to_sdr(struct crypto4xx_device *dev) 458049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 459049359d655277c382683a6030ae0bac485568ffcJames Hsiao unsigned long flags; 460049359d655277c382683a6030ae0bac485568ffcJames Hsiao 461049359d655277c382683a6030ae0bac485568ffcJames Hsiao spin_lock_irqsave(&dev->core_dev->lock, flags); 462049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (dev->sdr_tail == dev->sdr_head) { 463049359d655277c382683a6030ae0bac485568ffcJames Hsiao spin_unlock_irqrestore(&dev->core_dev->lock, flags); 464049359d655277c382683a6030ae0bac485568ffcJames Hsiao return 0; 465049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 466049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (dev->sdr_tail != PPC4XX_LAST_SD) 467049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->sdr_tail++; 468049359d655277c382683a6030ae0bac485568ffcJames Hsiao else 469049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->sdr_tail = 0; 470049359d655277c382683a6030ae0bac485568ffcJames Hsiao spin_unlock_irqrestore(&dev->core_dev->lock, flags); 471049359d655277c382683a6030ae0bac485568ffcJames Hsiao 472049359d655277c382683a6030ae0bac485568ffcJames Hsiao return 0; 473049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 474049359d655277c382683a6030ae0bac485568ffcJames Hsiao 475049359d655277c382683a6030ae0bac485568ffcJames Hsiaostatic inline struct ce_sd *crypto4xx_get_sdp(struct crypto4xx_device *dev, 476049359d655277c382683a6030ae0bac485568ffcJames Hsiao dma_addr_t *sd_dma, u32 idx) 477049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 478049359d655277c382683a6030ae0bac485568ffcJames Hsiao *sd_dma = dev->sdr_pa + sizeof(struct ce_sd) * idx; 479049359d655277c382683a6030ae0bac485568ffcJames Hsiao 480049359d655277c382683a6030ae0bac485568ffcJames Hsiao return (struct ce_sd *)(dev->sdr + sizeof(struct ce_sd) * idx); 481049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 482049359d655277c382683a6030ae0bac485568ffcJames Hsiao 483049359d655277c382683a6030ae0bac485568ffcJames Hsiaostatic u32 crypto4xx_fill_one_page(struct crypto4xx_device *dev, 484049359d655277c382683a6030ae0bac485568ffcJames Hsiao dma_addr_t *addr, u32 *length, 485049359d655277c382683a6030ae0bac485568ffcJames Hsiao u32 *idx, u32 *offset, u32 *nbytes) 486049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 487049359d655277c382683a6030ae0bac485568ffcJames Hsiao u32 len; 488049359d655277c382683a6030ae0bac485568ffcJames Hsiao 489049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (*length > dev->scatter_buffer_size) { 490049359d655277c382683a6030ae0bac485568ffcJames Hsiao memcpy(phys_to_virt(*addr), 491049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->scatter_buffer_va + 492049359d655277c382683a6030ae0bac485568ffcJames Hsiao *idx * dev->scatter_buffer_size + *offset, 493049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->scatter_buffer_size); 494049359d655277c382683a6030ae0bac485568ffcJames Hsiao *offset = 0; 495049359d655277c382683a6030ae0bac485568ffcJames Hsiao *length -= dev->scatter_buffer_size; 496049359d655277c382683a6030ae0bac485568ffcJames Hsiao *nbytes -= dev->scatter_buffer_size; 497049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (*idx == PPC4XX_LAST_SD) 498049359d655277c382683a6030ae0bac485568ffcJames Hsiao *idx = 0; 499049359d655277c382683a6030ae0bac485568ffcJames Hsiao else 500049359d655277c382683a6030ae0bac485568ffcJames Hsiao (*idx)++; 501049359d655277c382683a6030ae0bac485568ffcJames Hsiao *addr = *addr + dev->scatter_buffer_size; 502049359d655277c382683a6030ae0bac485568ffcJames Hsiao return 1; 503049359d655277c382683a6030ae0bac485568ffcJames Hsiao } else if (*length < dev->scatter_buffer_size) { 504049359d655277c382683a6030ae0bac485568ffcJames Hsiao memcpy(phys_to_virt(*addr), 505049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->scatter_buffer_va + 506049359d655277c382683a6030ae0bac485568ffcJames Hsiao *idx * dev->scatter_buffer_size + *offset, *length); 507049359d655277c382683a6030ae0bac485568ffcJames Hsiao if ((*offset + *length) == dev->scatter_buffer_size) { 508049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (*idx == PPC4XX_LAST_SD) 509049359d655277c382683a6030ae0bac485568ffcJames Hsiao *idx = 0; 510049359d655277c382683a6030ae0bac485568ffcJames Hsiao else 511049359d655277c382683a6030ae0bac485568ffcJames Hsiao (*idx)++; 512049359d655277c382683a6030ae0bac485568ffcJames Hsiao *nbytes -= *length; 513049359d655277c382683a6030ae0bac485568ffcJames Hsiao *offset = 0; 514049359d655277c382683a6030ae0bac485568ffcJames Hsiao } else { 515049359d655277c382683a6030ae0bac485568ffcJames Hsiao *nbytes -= *length; 516049359d655277c382683a6030ae0bac485568ffcJames Hsiao *offset += *length; 517049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 518049359d655277c382683a6030ae0bac485568ffcJames Hsiao 519049359d655277c382683a6030ae0bac485568ffcJames Hsiao return 0; 520049359d655277c382683a6030ae0bac485568ffcJames Hsiao } else { 521049359d655277c382683a6030ae0bac485568ffcJames Hsiao len = (*nbytes <= dev->scatter_buffer_size) ? 522049359d655277c382683a6030ae0bac485568ffcJames Hsiao (*nbytes) : dev->scatter_buffer_size; 523049359d655277c382683a6030ae0bac485568ffcJames Hsiao memcpy(phys_to_virt(*addr), 524049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->scatter_buffer_va + 525049359d655277c382683a6030ae0bac485568ffcJames Hsiao *idx * dev->scatter_buffer_size + *offset, 526049359d655277c382683a6030ae0bac485568ffcJames Hsiao len); 527049359d655277c382683a6030ae0bac485568ffcJames Hsiao *offset = 0; 528049359d655277c382683a6030ae0bac485568ffcJames Hsiao *nbytes -= len; 529049359d655277c382683a6030ae0bac485568ffcJames Hsiao 530049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (*idx == PPC4XX_LAST_SD) 531049359d655277c382683a6030ae0bac485568ffcJames Hsiao *idx = 0; 532049359d655277c382683a6030ae0bac485568ffcJames Hsiao else 533049359d655277c382683a6030ae0bac485568ffcJames Hsiao (*idx)++; 534049359d655277c382683a6030ae0bac485568ffcJames Hsiao 535049359d655277c382683a6030ae0bac485568ffcJames Hsiao return 0; 536049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 537049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 538049359d655277c382683a6030ae0bac485568ffcJames Hsiao 539049359d655277c382683a6030ae0bac485568ffcJames Hsiaostatic void crypto4xx_copy_pkt_to_dst(struct crypto4xx_device *dev, 540049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct ce_pd *pd, 541049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct pd_uinfo *pd_uinfo, 542049359d655277c382683a6030ae0bac485568ffcJames Hsiao u32 nbytes, 543049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct scatterlist *dst) 544049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 545049359d655277c382683a6030ae0bac485568ffcJames Hsiao dma_addr_t addr; 546049359d655277c382683a6030ae0bac485568ffcJames Hsiao u32 this_sd; 547049359d655277c382683a6030ae0bac485568ffcJames Hsiao u32 offset; 548049359d655277c382683a6030ae0bac485568ffcJames Hsiao u32 len; 549049359d655277c382683a6030ae0bac485568ffcJames Hsiao u32 i; 550049359d655277c382683a6030ae0bac485568ffcJames Hsiao u32 sg_len; 551049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct scatterlist *sg; 552049359d655277c382683a6030ae0bac485568ffcJames Hsiao 553049359d655277c382683a6030ae0bac485568ffcJames Hsiao this_sd = pd_uinfo->first_sd; 554049359d655277c382683a6030ae0bac485568ffcJames Hsiao offset = 0; 555049359d655277c382683a6030ae0bac485568ffcJames Hsiao i = 0; 556049359d655277c382683a6030ae0bac485568ffcJames Hsiao 557049359d655277c382683a6030ae0bac485568ffcJames Hsiao while (nbytes) { 558049359d655277c382683a6030ae0bac485568ffcJames Hsiao sg = &dst[i]; 559049359d655277c382683a6030ae0bac485568ffcJames Hsiao sg_len = sg->length; 560049359d655277c382683a6030ae0bac485568ffcJames Hsiao addr = dma_map_page(dev->core_dev->device, sg_page(sg), 561049359d655277c382683a6030ae0bac485568ffcJames Hsiao sg->offset, sg->length, DMA_TO_DEVICE); 562049359d655277c382683a6030ae0bac485568ffcJames Hsiao 563049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (offset == 0) { 564049359d655277c382683a6030ae0bac485568ffcJames Hsiao len = (nbytes <= sg->length) ? nbytes : sg->length; 565049359d655277c382683a6030ae0bac485568ffcJames Hsiao while (crypto4xx_fill_one_page(dev, &addr, &len, 566049359d655277c382683a6030ae0bac485568ffcJames Hsiao &this_sd, &offset, &nbytes)) 567049359d655277c382683a6030ae0bac485568ffcJames Hsiao ; 568049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (!nbytes) 569049359d655277c382683a6030ae0bac485568ffcJames Hsiao return; 570049359d655277c382683a6030ae0bac485568ffcJames Hsiao i++; 571049359d655277c382683a6030ae0bac485568ffcJames Hsiao } else { 572049359d655277c382683a6030ae0bac485568ffcJames Hsiao len = (nbytes <= (dev->scatter_buffer_size - offset)) ? 573049359d655277c382683a6030ae0bac485568ffcJames Hsiao nbytes : (dev->scatter_buffer_size - offset); 574049359d655277c382683a6030ae0bac485568ffcJames Hsiao len = (sg->length < len) ? sg->length : len; 575049359d655277c382683a6030ae0bac485568ffcJames Hsiao while (crypto4xx_fill_one_page(dev, &addr, &len, 576049359d655277c382683a6030ae0bac485568ffcJames Hsiao &this_sd, &offset, &nbytes)) 577049359d655277c382683a6030ae0bac485568ffcJames Hsiao ; 578049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (!nbytes) 579049359d655277c382683a6030ae0bac485568ffcJames Hsiao return; 580049359d655277c382683a6030ae0bac485568ffcJames Hsiao sg_len -= len; 581049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (sg_len) { 582049359d655277c382683a6030ae0bac485568ffcJames Hsiao addr += len; 583049359d655277c382683a6030ae0bac485568ffcJames Hsiao while (crypto4xx_fill_one_page(dev, &addr, 584049359d655277c382683a6030ae0bac485568ffcJames Hsiao &sg_len, &this_sd, &offset, &nbytes)) 585049359d655277c382683a6030ae0bac485568ffcJames Hsiao ; 586049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 587049359d655277c382683a6030ae0bac485568ffcJames Hsiao i++; 588049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 589049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 590049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 591049359d655277c382683a6030ae0bac485568ffcJames Hsiao 592049359d655277c382683a6030ae0bac485568ffcJames Hsiaostatic u32 crypto4xx_copy_digest_to_dst(struct pd_uinfo *pd_uinfo, 593049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct crypto4xx_ctx *ctx) 594049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 595049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct dynamic_sa_ctl *sa = (struct dynamic_sa_ctl *) ctx->sa_in; 596049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct sa_state_record *state_record = 597049359d655277c382683a6030ae0bac485568ffcJames Hsiao (struct sa_state_record *) pd_uinfo->sr_va; 598049359d655277c382683a6030ae0bac485568ffcJames Hsiao 599049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (sa->sa_command_0.bf.hash_alg == SA_HASH_ALG_SHA1) { 600049359d655277c382683a6030ae0bac485568ffcJames Hsiao memcpy((void *) pd_uinfo->dest_va, state_record->save_digest, 601049359d655277c382683a6030ae0bac485568ffcJames Hsiao SA_HASH_ALG_SHA1_DIGEST_SIZE); 602049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 603049359d655277c382683a6030ae0bac485568ffcJames Hsiao 604049359d655277c382683a6030ae0bac485568ffcJames Hsiao return 0; 605049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 606049359d655277c382683a6030ae0bac485568ffcJames Hsiao 607049359d655277c382683a6030ae0bac485568ffcJames Hsiaostatic void crypto4xx_ret_sg_desc(struct crypto4xx_device *dev, 608049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct pd_uinfo *pd_uinfo) 609049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 610049359d655277c382683a6030ae0bac485568ffcJames Hsiao int i; 611049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (pd_uinfo->num_gd) { 612049359d655277c382683a6030ae0bac485568ffcJames Hsiao for (i = 0; i < pd_uinfo->num_gd; i++) 613049359d655277c382683a6030ae0bac485568ffcJames Hsiao crypto4xx_put_gd_to_gdr(dev); 614049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd_uinfo->first_gd = 0xffffffff; 615049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd_uinfo->num_gd = 0; 616049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 617049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (pd_uinfo->num_sd) { 618049359d655277c382683a6030ae0bac485568ffcJames Hsiao for (i = 0; i < pd_uinfo->num_sd; i++) 619049359d655277c382683a6030ae0bac485568ffcJames Hsiao crypto4xx_put_sd_to_sdr(dev); 620049359d655277c382683a6030ae0bac485568ffcJames Hsiao 621049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd_uinfo->first_sd = 0xffffffff; 622049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd_uinfo->num_sd = 0; 623049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 624049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 625049359d655277c382683a6030ae0bac485568ffcJames Hsiao 626049359d655277c382683a6030ae0bac485568ffcJames Hsiaostatic u32 crypto4xx_ablkcipher_done(struct crypto4xx_device *dev, 627049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct pd_uinfo *pd_uinfo, 628049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct ce_pd *pd) 629049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 630049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct crypto4xx_ctx *ctx; 631049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct ablkcipher_request *ablk_req; 632049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct scatterlist *dst; 633049359d655277c382683a6030ae0bac485568ffcJames Hsiao dma_addr_t addr; 634049359d655277c382683a6030ae0bac485568ffcJames Hsiao 635049359d655277c382683a6030ae0bac485568ffcJames Hsiao ablk_req = ablkcipher_request_cast(pd_uinfo->async_req); 636049359d655277c382683a6030ae0bac485568ffcJames Hsiao ctx = crypto_tfm_ctx(ablk_req->base.tfm); 637049359d655277c382683a6030ae0bac485568ffcJames Hsiao 638049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (pd_uinfo->using_sd) { 639049359d655277c382683a6030ae0bac485568ffcJames Hsiao crypto4xx_copy_pkt_to_dst(dev, pd, pd_uinfo, ablk_req->nbytes, 640049359d655277c382683a6030ae0bac485568ffcJames Hsiao ablk_req->dst); 641049359d655277c382683a6030ae0bac485568ffcJames Hsiao } else { 642049359d655277c382683a6030ae0bac485568ffcJames Hsiao dst = pd_uinfo->dest_va; 643049359d655277c382683a6030ae0bac485568ffcJames Hsiao addr = dma_map_page(dev->core_dev->device, sg_page(dst), 644049359d655277c382683a6030ae0bac485568ffcJames Hsiao dst->offset, dst->length, DMA_FROM_DEVICE); 645049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 646049359d655277c382683a6030ae0bac485568ffcJames Hsiao crypto4xx_ret_sg_desc(dev, pd_uinfo); 647049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (ablk_req->base.complete != NULL) 648049359d655277c382683a6030ae0bac485568ffcJames Hsiao ablk_req->base.complete(&ablk_req->base, 0); 649049359d655277c382683a6030ae0bac485568ffcJames Hsiao 650049359d655277c382683a6030ae0bac485568ffcJames Hsiao return 0; 651049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 652049359d655277c382683a6030ae0bac485568ffcJames Hsiao 653049359d655277c382683a6030ae0bac485568ffcJames Hsiaostatic u32 crypto4xx_ahash_done(struct crypto4xx_device *dev, 654049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct pd_uinfo *pd_uinfo) 655049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 656049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct crypto4xx_ctx *ctx; 657049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct ahash_request *ahash_req; 658049359d655277c382683a6030ae0bac485568ffcJames Hsiao 659049359d655277c382683a6030ae0bac485568ffcJames Hsiao ahash_req = ahash_request_cast(pd_uinfo->async_req); 660049359d655277c382683a6030ae0bac485568ffcJames Hsiao ctx = crypto_tfm_ctx(ahash_req->base.tfm); 661049359d655277c382683a6030ae0bac485568ffcJames Hsiao 662049359d655277c382683a6030ae0bac485568ffcJames Hsiao crypto4xx_copy_digest_to_dst(pd_uinfo, 663049359d655277c382683a6030ae0bac485568ffcJames Hsiao crypto_tfm_ctx(ahash_req->base.tfm)); 664049359d655277c382683a6030ae0bac485568ffcJames Hsiao crypto4xx_ret_sg_desc(dev, pd_uinfo); 665049359d655277c382683a6030ae0bac485568ffcJames Hsiao /* call user provided callback function x */ 666049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (ahash_req->base.complete != NULL) 667049359d655277c382683a6030ae0bac485568ffcJames Hsiao ahash_req->base.complete(&ahash_req->base, 0); 668049359d655277c382683a6030ae0bac485568ffcJames Hsiao 669049359d655277c382683a6030ae0bac485568ffcJames Hsiao return 0; 670049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 671049359d655277c382683a6030ae0bac485568ffcJames Hsiao 672049359d655277c382683a6030ae0bac485568ffcJames Hsiaostatic u32 crypto4xx_pd_done(struct crypto4xx_device *dev, u32 idx) 673049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 674049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct ce_pd *pd; 675049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct pd_uinfo *pd_uinfo; 676049359d655277c382683a6030ae0bac485568ffcJames Hsiao 677049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd = dev->pdr + sizeof(struct ce_pd)*idx; 678049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd_uinfo = dev->pdr_uinfo + sizeof(struct pd_uinfo)*idx; 679049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (crypto_tfm_alg_type(pd_uinfo->async_req->tfm) == 680049359d655277c382683a6030ae0bac485568ffcJames Hsiao CRYPTO_ALG_TYPE_ABLKCIPHER) 681049359d655277c382683a6030ae0bac485568ffcJames Hsiao return crypto4xx_ablkcipher_done(dev, pd_uinfo, pd); 682049359d655277c382683a6030ae0bac485568ffcJames Hsiao else 683049359d655277c382683a6030ae0bac485568ffcJames Hsiao return crypto4xx_ahash_done(dev, pd_uinfo); 684049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 685049359d655277c382683a6030ae0bac485568ffcJames Hsiao 686049359d655277c382683a6030ae0bac485568ffcJames Hsiao/** 687049359d655277c382683a6030ae0bac485568ffcJames Hsiao * Note: Only use this function to copy items that is word aligned. 688049359d655277c382683a6030ae0bac485568ffcJames Hsiao */ 689049359d655277c382683a6030ae0bac485568ffcJames Hsiaovoid crypto4xx_memcpy_le(unsigned int *dst, 690049359d655277c382683a6030ae0bac485568ffcJames Hsiao const unsigned char *buf, 691049359d655277c382683a6030ae0bac485568ffcJames Hsiao int len) 692049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 693049359d655277c382683a6030ae0bac485568ffcJames Hsiao u8 *tmp; 694049359d655277c382683a6030ae0bac485568ffcJames Hsiao for (; len >= 4; buf += 4, len -= 4) 695049359d655277c382683a6030ae0bac485568ffcJames Hsiao *dst++ = cpu_to_le32(*(unsigned int *) buf); 696049359d655277c382683a6030ae0bac485568ffcJames Hsiao 697049359d655277c382683a6030ae0bac485568ffcJames Hsiao tmp = (u8 *)dst; 698049359d655277c382683a6030ae0bac485568ffcJames Hsiao switch (len) { 699049359d655277c382683a6030ae0bac485568ffcJames Hsiao case 3: 700049359d655277c382683a6030ae0bac485568ffcJames Hsiao *tmp++ = 0; 701049359d655277c382683a6030ae0bac485568ffcJames Hsiao *tmp++ = *(buf+2); 702049359d655277c382683a6030ae0bac485568ffcJames Hsiao *tmp++ = *(buf+1); 703049359d655277c382683a6030ae0bac485568ffcJames Hsiao *tmp++ = *buf; 704049359d655277c382683a6030ae0bac485568ffcJames Hsiao break; 705049359d655277c382683a6030ae0bac485568ffcJames Hsiao case 2: 706049359d655277c382683a6030ae0bac485568ffcJames Hsiao *tmp++ = 0; 707049359d655277c382683a6030ae0bac485568ffcJames Hsiao *tmp++ = 0; 708049359d655277c382683a6030ae0bac485568ffcJames Hsiao *tmp++ = *(buf+1); 709049359d655277c382683a6030ae0bac485568ffcJames Hsiao *tmp++ = *buf; 710049359d655277c382683a6030ae0bac485568ffcJames Hsiao break; 711049359d655277c382683a6030ae0bac485568ffcJames Hsiao case 1: 712049359d655277c382683a6030ae0bac485568ffcJames Hsiao *tmp++ = 0; 713049359d655277c382683a6030ae0bac485568ffcJames Hsiao *tmp++ = 0; 714049359d655277c382683a6030ae0bac485568ffcJames Hsiao *tmp++ = 0; 715049359d655277c382683a6030ae0bac485568ffcJames Hsiao *tmp++ = *buf; 716049359d655277c382683a6030ae0bac485568ffcJames Hsiao break; 717049359d655277c382683a6030ae0bac485568ffcJames Hsiao default: 718049359d655277c382683a6030ae0bac485568ffcJames Hsiao break; 719049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 720049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 721049359d655277c382683a6030ae0bac485568ffcJames Hsiao 722049359d655277c382683a6030ae0bac485568ffcJames Hsiaostatic void crypto4xx_stop_all(struct crypto4xx_core_device *core_dev) 723049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 724049359d655277c382683a6030ae0bac485568ffcJames Hsiao crypto4xx_destroy_pdr(core_dev->dev); 725049359d655277c382683a6030ae0bac485568ffcJames Hsiao crypto4xx_destroy_gdr(core_dev->dev); 726049359d655277c382683a6030ae0bac485568ffcJames Hsiao crypto4xx_destroy_sdr(core_dev->dev); 727049359d655277c382683a6030ae0bac485568ffcJames Hsiao iounmap(core_dev->dev->ce_base); 728049359d655277c382683a6030ae0bac485568ffcJames Hsiao kfree(core_dev->dev); 729049359d655277c382683a6030ae0bac485568ffcJames Hsiao kfree(core_dev); 730049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 731049359d655277c382683a6030ae0bac485568ffcJames Hsiao 732049359d655277c382683a6030ae0bac485568ffcJames Hsiaovoid crypto4xx_return_pd(struct crypto4xx_device *dev, 733049359d655277c382683a6030ae0bac485568ffcJames Hsiao u32 pd_entry, struct ce_pd *pd, 734049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct pd_uinfo *pd_uinfo) 735049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 736049359d655277c382683a6030ae0bac485568ffcJames Hsiao /* irq should be already disabled */ 737049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->pdr_head = pd_entry; 738049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd->pd_ctl.w = 0; 739049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd->pd_ctl_len.w = 0; 740049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd_uinfo->state = PD_ENTRY_FREE; 741049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 742049359d655277c382683a6030ae0bac485568ffcJames Hsiao 743049359d655277c382683a6030ae0bac485568ffcJames Hsiao/* 744049359d655277c382683a6030ae0bac485568ffcJames Hsiao * derive number of elements in scatterlist 745049359d655277c382683a6030ae0bac485568ffcJames Hsiao * Shamlessly copy from talitos.c 746049359d655277c382683a6030ae0bac485568ffcJames Hsiao */ 747049359d655277c382683a6030ae0bac485568ffcJames Hsiaostatic int get_sg_count(struct scatterlist *sg_list, int nbytes) 748049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 749049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct scatterlist *sg = sg_list; 750049359d655277c382683a6030ae0bac485568ffcJames Hsiao int sg_nents = 0; 751049359d655277c382683a6030ae0bac485568ffcJames Hsiao 752049359d655277c382683a6030ae0bac485568ffcJames Hsiao while (nbytes) { 753049359d655277c382683a6030ae0bac485568ffcJames Hsiao sg_nents++; 754049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (sg->length > nbytes) 755049359d655277c382683a6030ae0bac485568ffcJames Hsiao break; 756049359d655277c382683a6030ae0bac485568ffcJames Hsiao nbytes -= sg->length; 757049359d655277c382683a6030ae0bac485568ffcJames Hsiao sg = sg_next(sg); 758049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 759049359d655277c382683a6030ae0bac485568ffcJames Hsiao 760049359d655277c382683a6030ae0bac485568ffcJames Hsiao return sg_nents; 761049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 762049359d655277c382683a6030ae0bac485568ffcJames Hsiao 763049359d655277c382683a6030ae0bac485568ffcJames Hsiaostatic u32 get_next_gd(u32 current) 764049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 765049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (current != PPC4XX_LAST_GD) 766049359d655277c382683a6030ae0bac485568ffcJames Hsiao return current + 1; 767049359d655277c382683a6030ae0bac485568ffcJames Hsiao else 768049359d655277c382683a6030ae0bac485568ffcJames Hsiao return 0; 769049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 770049359d655277c382683a6030ae0bac485568ffcJames Hsiao 771049359d655277c382683a6030ae0bac485568ffcJames Hsiaostatic u32 get_next_sd(u32 current) 772049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 773049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (current != PPC4XX_LAST_SD) 774049359d655277c382683a6030ae0bac485568ffcJames Hsiao return current + 1; 775049359d655277c382683a6030ae0bac485568ffcJames Hsiao else 776049359d655277c382683a6030ae0bac485568ffcJames Hsiao return 0; 777049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 778049359d655277c382683a6030ae0bac485568ffcJames Hsiao 779049359d655277c382683a6030ae0bac485568ffcJames Hsiaou32 crypto4xx_build_pd(struct crypto_async_request *req, 780049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct crypto4xx_ctx *ctx, 781049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct scatterlist *src, 782049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct scatterlist *dst, 783049359d655277c382683a6030ae0bac485568ffcJames Hsiao unsigned int datalen, 784049359d655277c382683a6030ae0bac485568ffcJames Hsiao void *iv, u32 iv_len) 785049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 786049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct crypto4xx_device *dev = ctx->dev; 787049359d655277c382683a6030ae0bac485568ffcJames Hsiao dma_addr_t addr, pd_dma, sd_dma, gd_dma; 788049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct dynamic_sa_ctl *sa; 789049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct scatterlist *sg; 790049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct ce_gd *gd; 791049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct ce_pd *pd; 792049359d655277c382683a6030ae0bac485568ffcJames Hsiao u32 num_gd, num_sd; 793049359d655277c382683a6030ae0bac485568ffcJames Hsiao u32 fst_gd = 0xffffffff; 794049359d655277c382683a6030ae0bac485568ffcJames Hsiao u32 fst_sd = 0xffffffff; 795049359d655277c382683a6030ae0bac485568ffcJames Hsiao u32 pd_entry; 796049359d655277c382683a6030ae0bac485568ffcJames Hsiao unsigned long flags; 797049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct pd_uinfo *pd_uinfo = NULL; 798049359d655277c382683a6030ae0bac485568ffcJames Hsiao unsigned int nbytes = datalen, idx; 799049359d655277c382683a6030ae0bac485568ffcJames Hsiao unsigned int ivlen = 0; 800049359d655277c382683a6030ae0bac485568ffcJames Hsiao u32 gd_idx = 0; 801049359d655277c382683a6030ae0bac485568ffcJames Hsiao 802049359d655277c382683a6030ae0bac485568ffcJames Hsiao /* figure how many gd is needed */ 803049359d655277c382683a6030ae0bac485568ffcJames Hsiao num_gd = get_sg_count(src, datalen); 804049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (num_gd == 1) 805049359d655277c382683a6030ae0bac485568ffcJames Hsiao num_gd = 0; 806049359d655277c382683a6030ae0bac485568ffcJames Hsiao 807049359d655277c382683a6030ae0bac485568ffcJames Hsiao /* figure how many sd is needed */ 808049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (sg_is_last(dst) || ctx->is_hash) { 809049359d655277c382683a6030ae0bac485568ffcJames Hsiao num_sd = 0; 810049359d655277c382683a6030ae0bac485568ffcJames Hsiao } else { 811049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (datalen > PPC4XX_SD_BUFFER_SIZE) { 812049359d655277c382683a6030ae0bac485568ffcJames Hsiao num_sd = datalen / PPC4XX_SD_BUFFER_SIZE; 813049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (datalen % PPC4XX_SD_BUFFER_SIZE) 814049359d655277c382683a6030ae0bac485568ffcJames Hsiao num_sd++; 815049359d655277c382683a6030ae0bac485568ffcJames Hsiao } else { 816049359d655277c382683a6030ae0bac485568ffcJames Hsiao num_sd = 1; 817049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 818049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 819049359d655277c382683a6030ae0bac485568ffcJames Hsiao 820049359d655277c382683a6030ae0bac485568ffcJames Hsiao /* 821049359d655277c382683a6030ae0bac485568ffcJames Hsiao * The follow section of code needs to be protected 822049359d655277c382683a6030ae0bac485568ffcJames Hsiao * The gather ring and scatter ring needs to be consecutive 823049359d655277c382683a6030ae0bac485568ffcJames Hsiao * In case of run out of any kind of descriptor, the descriptor 824049359d655277c382683a6030ae0bac485568ffcJames Hsiao * already got must be return the original place. 825049359d655277c382683a6030ae0bac485568ffcJames Hsiao */ 826049359d655277c382683a6030ae0bac485568ffcJames Hsiao spin_lock_irqsave(&dev->core_dev->lock, flags); 827049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (num_gd) { 828049359d655277c382683a6030ae0bac485568ffcJames Hsiao fst_gd = crypto4xx_get_n_gd(dev, num_gd); 829049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (fst_gd == ERING_WAS_FULL) { 830049359d655277c382683a6030ae0bac485568ffcJames Hsiao spin_unlock_irqrestore(&dev->core_dev->lock, flags); 831049359d655277c382683a6030ae0bac485568ffcJames Hsiao return -EAGAIN; 832049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 833049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 834049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (num_sd) { 835049359d655277c382683a6030ae0bac485568ffcJames Hsiao fst_sd = crypto4xx_get_n_sd(dev, num_sd); 836049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (fst_sd == ERING_WAS_FULL) { 837049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (num_gd) 838049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->gdr_head = fst_gd; 839049359d655277c382683a6030ae0bac485568ffcJames Hsiao spin_unlock_irqrestore(&dev->core_dev->lock, flags); 840049359d655277c382683a6030ae0bac485568ffcJames Hsiao return -EAGAIN; 841049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 842049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 843049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd_entry = crypto4xx_get_pd_from_pdr_nolock(dev); 844049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (pd_entry == ERING_WAS_FULL) { 845049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (num_gd) 846049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->gdr_head = fst_gd; 847049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (num_sd) 848049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev->sdr_head = fst_sd; 849049359d655277c382683a6030ae0bac485568ffcJames Hsiao spin_unlock_irqrestore(&dev->core_dev->lock, flags); 850049359d655277c382683a6030ae0bac485568ffcJames Hsiao return -EAGAIN; 851049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 852049359d655277c382683a6030ae0bac485568ffcJames Hsiao spin_unlock_irqrestore(&dev->core_dev->lock, flags); 853049359d655277c382683a6030ae0bac485568ffcJames Hsiao 854049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd_uinfo = (struct pd_uinfo *)(dev->pdr_uinfo + 855049359d655277c382683a6030ae0bac485568ffcJames Hsiao sizeof(struct pd_uinfo) * pd_entry); 856049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd = crypto4xx_get_pdp(dev, &pd_dma, pd_entry); 857049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd_uinfo->async_req = req; 858049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd_uinfo->num_gd = num_gd; 859049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd_uinfo->num_sd = num_sd; 860049359d655277c382683a6030ae0bac485568ffcJames Hsiao 861049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (iv_len || ctx->is_hash) { 862049359d655277c382683a6030ae0bac485568ffcJames Hsiao ivlen = iv_len; 863049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd->sa = pd_uinfo->sa_pa; 864049359d655277c382683a6030ae0bac485568ffcJames Hsiao sa = (struct dynamic_sa_ctl *) pd_uinfo->sa_va; 865049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (ctx->direction == DIR_INBOUND) 866049359d655277c382683a6030ae0bac485568ffcJames Hsiao memcpy(sa, ctx->sa_in, ctx->sa_len * 4); 867049359d655277c382683a6030ae0bac485568ffcJames Hsiao else 868049359d655277c382683a6030ae0bac485568ffcJames Hsiao memcpy(sa, ctx->sa_out, ctx->sa_len * 4); 869049359d655277c382683a6030ae0bac485568ffcJames Hsiao 870049359d655277c382683a6030ae0bac485568ffcJames Hsiao memcpy((void *) sa + ctx->offset_to_sr_ptr, 871049359d655277c382683a6030ae0bac485568ffcJames Hsiao &pd_uinfo->sr_pa, 4); 872049359d655277c382683a6030ae0bac485568ffcJames Hsiao 873049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (iv_len) 874049359d655277c382683a6030ae0bac485568ffcJames Hsiao crypto4xx_memcpy_le(pd_uinfo->sr_va, iv, iv_len); 875049359d655277c382683a6030ae0bac485568ffcJames Hsiao } else { 876049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (ctx->direction == DIR_INBOUND) { 877049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd->sa = ctx->sa_in_dma_addr; 878049359d655277c382683a6030ae0bac485568ffcJames Hsiao sa = (struct dynamic_sa_ctl *) ctx->sa_in; 879049359d655277c382683a6030ae0bac485568ffcJames Hsiao } else { 880049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd->sa = ctx->sa_out_dma_addr; 881049359d655277c382683a6030ae0bac485568ffcJames Hsiao sa = (struct dynamic_sa_ctl *) ctx->sa_out; 882049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 883049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 884049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd->sa_len = ctx->sa_len; 885049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (num_gd) { 886049359d655277c382683a6030ae0bac485568ffcJames Hsiao /* get first gd we are going to use */ 887049359d655277c382683a6030ae0bac485568ffcJames Hsiao gd_idx = fst_gd; 888049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd_uinfo->first_gd = fst_gd; 889049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd_uinfo->num_gd = num_gd; 890049359d655277c382683a6030ae0bac485568ffcJames Hsiao gd = crypto4xx_get_gdp(dev, &gd_dma, gd_idx); 891049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd->src = gd_dma; 892049359d655277c382683a6030ae0bac485568ffcJames Hsiao /* enable gather */ 893049359d655277c382683a6030ae0bac485568ffcJames Hsiao sa->sa_command_0.bf.gather = 1; 894049359d655277c382683a6030ae0bac485568ffcJames Hsiao idx = 0; 895049359d655277c382683a6030ae0bac485568ffcJames Hsiao src = &src[0]; 896049359d655277c382683a6030ae0bac485568ffcJames Hsiao /* walk the sg, and setup gather array */ 897049359d655277c382683a6030ae0bac485568ffcJames Hsiao while (nbytes) { 898049359d655277c382683a6030ae0bac485568ffcJames Hsiao sg = &src[idx]; 899049359d655277c382683a6030ae0bac485568ffcJames Hsiao addr = dma_map_page(dev->core_dev->device, sg_page(sg), 900049359d655277c382683a6030ae0bac485568ffcJames Hsiao sg->offset, sg->length, DMA_TO_DEVICE); 901049359d655277c382683a6030ae0bac485568ffcJames Hsiao gd->ptr = addr; 902049359d655277c382683a6030ae0bac485568ffcJames Hsiao gd->ctl_len.len = sg->length; 903049359d655277c382683a6030ae0bac485568ffcJames Hsiao gd->ctl_len.done = 0; 904049359d655277c382683a6030ae0bac485568ffcJames Hsiao gd->ctl_len.ready = 1; 905049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (sg->length >= nbytes) 906049359d655277c382683a6030ae0bac485568ffcJames Hsiao break; 907049359d655277c382683a6030ae0bac485568ffcJames Hsiao nbytes -= sg->length; 908049359d655277c382683a6030ae0bac485568ffcJames Hsiao gd_idx = get_next_gd(gd_idx); 909049359d655277c382683a6030ae0bac485568ffcJames Hsiao gd = crypto4xx_get_gdp(dev, &gd_dma, gd_idx); 910049359d655277c382683a6030ae0bac485568ffcJames Hsiao idx++; 911049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 912049359d655277c382683a6030ae0bac485568ffcJames Hsiao } else { 913049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd->src = (u32)dma_map_page(dev->core_dev->device, sg_page(src), 914049359d655277c382683a6030ae0bac485568ffcJames Hsiao src->offset, src->length, DMA_TO_DEVICE); 915049359d655277c382683a6030ae0bac485568ffcJames Hsiao /* 916049359d655277c382683a6030ae0bac485568ffcJames Hsiao * Disable gather in sa command 917049359d655277c382683a6030ae0bac485568ffcJames Hsiao */ 918049359d655277c382683a6030ae0bac485568ffcJames Hsiao sa->sa_command_0.bf.gather = 0; 919049359d655277c382683a6030ae0bac485568ffcJames Hsiao /* 920049359d655277c382683a6030ae0bac485568ffcJames Hsiao * Indicate gather array is not used 921049359d655277c382683a6030ae0bac485568ffcJames Hsiao */ 922049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd_uinfo->first_gd = 0xffffffff; 923049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd_uinfo->num_gd = 0; 924049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 925049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (ctx->is_hash || sg_is_last(dst)) { 926049359d655277c382683a6030ae0bac485568ffcJames Hsiao /* 927049359d655277c382683a6030ae0bac485568ffcJames Hsiao * we know application give us dst a whole piece of memory 928049359d655277c382683a6030ae0bac485568ffcJames Hsiao * no need to use scatter ring. 929049359d655277c382683a6030ae0bac485568ffcJames Hsiao * In case of is_hash, the icv is always at end of src data. 930049359d655277c382683a6030ae0bac485568ffcJames Hsiao */ 931049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd_uinfo->using_sd = 0; 932049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd_uinfo->first_sd = 0xffffffff; 933049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd_uinfo->num_sd = 0; 934049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd_uinfo->dest_va = dst; 935049359d655277c382683a6030ae0bac485568ffcJames Hsiao sa->sa_command_0.bf.scatter = 0; 936049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (ctx->is_hash) 937049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd->dest = virt_to_phys((void *)dst); 938049359d655277c382683a6030ae0bac485568ffcJames Hsiao else 939049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd->dest = (u32)dma_map_page(dev->core_dev->device, 940049359d655277c382683a6030ae0bac485568ffcJames Hsiao sg_page(dst), dst->offset, 941049359d655277c382683a6030ae0bac485568ffcJames Hsiao dst->length, DMA_TO_DEVICE); 942049359d655277c382683a6030ae0bac485568ffcJames Hsiao } else { 943049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct ce_sd *sd = NULL; 944049359d655277c382683a6030ae0bac485568ffcJames Hsiao u32 sd_idx = fst_sd; 945049359d655277c382683a6030ae0bac485568ffcJames Hsiao nbytes = datalen; 946049359d655277c382683a6030ae0bac485568ffcJames Hsiao sa->sa_command_0.bf.scatter = 1; 947049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd_uinfo->using_sd = 1; 948049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd_uinfo->dest_va = dst; 949049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd_uinfo->first_sd = fst_sd; 950049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd_uinfo->num_sd = num_sd; 951049359d655277c382683a6030ae0bac485568ffcJames Hsiao sd = crypto4xx_get_sdp(dev, &sd_dma, sd_idx); 952049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd->dest = sd_dma; 953049359d655277c382683a6030ae0bac485568ffcJames Hsiao /* setup scatter descriptor */ 954049359d655277c382683a6030ae0bac485568ffcJames Hsiao sd->ctl.done = 0; 955049359d655277c382683a6030ae0bac485568ffcJames Hsiao sd->ctl.rdy = 1; 956049359d655277c382683a6030ae0bac485568ffcJames Hsiao /* sd->ptr should be setup by sd_init routine*/ 957049359d655277c382683a6030ae0bac485568ffcJames Hsiao idx = 0; 958049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (nbytes >= PPC4XX_SD_BUFFER_SIZE) 959049359d655277c382683a6030ae0bac485568ffcJames Hsiao nbytes -= PPC4XX_SD_BUFFER_SIZE; 960049359d655277c382683a6030ae0bac485568ffcJames Hsiao else 961049359d655277c382683a6030ae0bac485568ffcJames Hsiao nbytes = 0; 962049359d655277c382683a6030ae0bac485568ffcJames Hsiao while (nbytes) { 963049359d655277c382683a6030ae0bac485568ffcJames Hsiao sd_idx = get_next_sd(sd_idx); 964049359d655277c382683a6030ae0bac485568ffcJames Hsiao sd = crypto4xx_get_sdp(dev, &sd_dma, sd_idx); 965049359d655277c382683a6030ae0bac485568ffcJames Hsiao /* setup scatter descriptor */ 966049359d655277c382683a6030ae0bac485568ffcJames Hsiao sd->ctl.done = 0; 967049359d655277c382683a6030ae0bac485568ffcJames Hsiao sd->ctl.rdy = 1; 968049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (nbytes >= PPC4XX_SD_BUFFER_SIZE) 969049359d655277c382683a6030ae0bac485568ffcJames Hsiao nbytes -= PPC4XX_SD_BUFFER_SIZE; 970049359d655277c382683a6030ae0bac485568ffcJames Hsiao else 971049359d655277c382683a6030ae0bac485568ffcJames Hsiao /* 972049359d655277c382683a6030ae0bac485568ffcJames Hsiao * SD entry can hold PPC4XX_SD_BUFFER_SIZE, 973049359d655277c382683a6030ae0bac485568ffcJames Hsiao * which is more than nbytes, so done. 974049359d655277c382683a6030ae0bac485568ffcJames Hsiao */ 975049359d655277c382683a6030ae0bac485568ffcJames Hsiao nbytes = 0; 976049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 977049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 978049359d655277c382683a6030ae0bac485568ffcJames Hsiao 979049359d655277c382683a6030ae0bac485568ffcJames Hsiao sa->sa_command_1.bf.hash_crypto_offset = 0; 980049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd->pd_ctl.w = ctx->pd_ctl; 981049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd->pd_ctl_len.w = 0x00400000 | (ctx->bypass << 24) | datalen; 982049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd_uinfo->state = PD_ENTRY_INUSE; 983049359d655277c382683a6030ae0bac485568ffcJames Hsiao wmb(); 984049359d655277c382683a6030ae0bac485568ffcJames Hsiao /* write any value to push engine to read a pd */ 985049359d655277c382683a6030ae0bac485568ffcJames Hsiao writel(1, dev->ce_base + CRYPTO4XX_INT_DESCR_RD); 986049359d655277c382683a6030ae0bac485568ffcJames Hsiao return -EINPROGRESS; 987049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 988049359d655277c382683a6030ae0bac485568ffcJames Hsiao 989049359d655277c382683a6030ae0bac485568ffcJames Hsiao/** 990049359d655277c382683a6030ae0bac485568ffcJames Hsiao * Algorithm Registration Functions 991049359d655277c382683a6030ae0bac485568ffcJames Hsiao */ 992049359d655277c382683a6030ae0bac485568ffcJames Hsiaostatic int crypto4xx_alg_init(struct crypto_tfm *tfm) 993049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 994049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct crypto_alg *alg = tfm->__crt_alg; 995049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct crypto4xx_alg *amcc_alg = crypto_alg_to_crypto4xx_alg(alg); 996049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct crypto4xx_ctx *ctx = crypto_tfm_ctx(tfm); 997049359d655277c382683a6030ae0bac485568ffcJames Hsiao 998049359d655277c382683a6030ae0bac485568ffcJames Hsiao ctx->dev = amcc_alg->dev; 999049359d655277c382683a6030ae0bac485568ffcJames Hsiao ctx->sa_in = NULL; 1000049359d655277c382683a6030ae0bac485568ffcJames Hsiao ctx->sa_out = NULL; 1001049359d655277c382683a6030ae0bac485568ffcJames Hsiao ctx->sa_in_dma_addr = 0; 1002049359d655277c382683a6030ae0bac485568ffcJames Hsiao ctx->sa_out_dma_addr = 0; 1003049359d655277c382683a6030ae0bac485568ffcJames Hsiao ctx->sa_len = 0; 1004049359d655277c382683a6030ae0bac485568ffcJames Hsiao 10054dc10c0142ce0af8c20ec44dc6928ae63ad4f73aHerbert Xu switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) { 10064dc10c0142ce0af8c20ec44dc6928ae63ad4f73aHerbert Xu default: 1007049359d655277c382683a6030ae0bac485568ffcJames Hsiao tfm->crt_ablkcipher.reqsize = sizeof(struct crypto4xx_ctx); 10084dc10c0142ce0af8c20ec44dc6928ae63ad4f73aHerbert Xu break; 10094dc10c0142ce0af8c20ec44dc6928ae63ad4f73aHerbert Xu case CRYPTO_ALG_TYPE_AHASH: 10106b1679f4a006acb5d76f8df686aa44c63d2555b4Herbert Xu crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), 10116b1679f4a006acb5d76f8df686aa44c63d2555b4Herbert Xu sizeof(struct crypto4xx_ctx)); 10124dc10c0142ce0af8c20ec44dc6928ae63ad4f73aHerbert Xu break; 10134dc10c0142ce0af8c20ec44dc6928ae63ad4f73aHerbert Xu } 1014049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1015049359d655277c382683a6030ae0bac485568ffcJames Hsiao return 0; 1016049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 1017049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1018049359d655277c382683a6030ae0bac485568ffcJames Hsiaostatic void crypto4xx_alg_exit(struct crypto_tfm *tfm) 1019049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 1020049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct crypto4xx_ctx *ctx = crypto_tfm_ctx(tfm); 1021049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1022049359d655277c382683a6030ae0bac485568ffcJames Hsiao crypto4xx_free_sa(ctx); 1023049359d655277c382683a6030ae0bac485568ffcJames Hsiao crypto4xx_free_state_record(ctx); 1024049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 1025049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1026049359d655277c382683a6030ae0bac485568ffcJames Hsiaoint crypto4xx_register_alg(struct crypto4xx_device *sec_dev, 10274dc10c0142ce0af8c20ec44dc6928ae63ad4f73aHerbert Xu struct crypto4xx_alg_common *crypto_alg, 10284dc10c0142ce0af8c20ec44dc6928ae63ad4f73aHerbert Xu int array_size) 1029049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 1030049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct crypto4xx_alg *alg; 1031049359d655277c382683a6030ae0bac485568ffcJames Hsiao int i; 1032049359d655277c382683a6030ae0bac485568ffcJames Hsiao int rc = 0; 1033049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1034049359d655277c382683a6030ae0bac485568ffcJames Hsiao for (i = 0; i < array_size; i++) { 1035049359d655277c382683a6030ae0bac485568ffcJames Hsiao alg = kzalloc(sizeof(struct crypto4xx_alg), GFP_KERNEL); 1036049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (!alg) 1037049359d655277c382683a6030ae0bac485568ffcJames Hsiao return -ENOMEM; 1038049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1039049359d655277c382683a6030ae0bac485568ffcJames Hsiao alg->alg = crypto_alg[i]; 1040049359d655277c382683a6030ae0bac485568ffcJames Hsiao alg->dev = sec_dev; 10414dc10c0142ce0af8c20ec44dc6928ae63ad4f73aHerbert Xu 10424dc10c0142ce0af8c20ec44dc6928ae63ad4f73aHerbert Xu switch (alg->alg.type) { 10434dc10c0142ce0af8c20ec44dc6928ae63ad4f73aHerbert Xu case CRYPTO_ALG_TYPE_AHASH: 10444dc10c0142ce0af8c20ec44dc6928ae63ad4f73aHerbert Xu rc = crypto_register_ahash(&alg->alg.u.hash); 10454dc10c0142ce0af8c20ec44dc6928ae63ad4f73aHerbert Xu break; 10464dc10c0142ce0af8c20ec44dc6928ae63ad4f73aHerbert Xu 10474dc10c0142ce0af8c20ec44dc6928ae63ad4f73aHerbert Xu default: 10484dc10c0142ce0af8c20ec44dc6928ae63ad4f73aHerbert Xu rc = crypto_register_alg(&alg->alg.u.cipher); 10494dc10c0142ce0af8c20ec44dc6928ae63ad4f73aHerbert Xu break; 10504dc10c0142ce0af8c20ec44dc6928ae63ad4f73aHerbert Xu } 10514dc10c0142ce0af8c20ec44dc6928ae63ad4f73aHerbert Xu 1052049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (rc) { 1053049359d655277c382683a6030ae0bac485568ffcJames Hsiao list_del(&alg->entry); 1054049359d655277c382683a6030ae0bac485568ffcJames Hsiao kfree(alg); 1055049359d655277c382683a6030ae0bac485568ffcJames Hsiao } else { 1056049359d655277c382683a6030ae0bac485568ffcJames Hsiao list_add_tail(&alg->entry, &sec_dev->alg_list); 1057049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 1058049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 1059049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1060049359d655277c382683a6030ae0bac485568ffcJames Hsiao return 0; 1061049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 1062049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1063049359d655277c382683a6030ae0bac485568ffcJames Hsiaostatic void crypto4xx_unregister_alg(struct crypto4xx_device *sec_dev) 1064049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 1065049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct crypto4xx_alg *alg, *tmp; 1066049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1067049359d655277c382683a6030ae0bac485568ffcJames Hsiao list_for_each_entry_safe(alg, tmp, &sec_dev->alg_list, entry) { 1068049359d655277c382683a6030ae0bac485568ffcJames Hsiao list_del(&alg->entry); 10694dc10c0142ce0af8c20ec44dc6928ae63ad4f73aHerbert Xu switch (alg->alg.type) { 10704dc10c0142ce0af8c20ec44dc6928ae63ad4f73aHerbert Xu case CRYPTO_ALG_TYPE_AHASH: 10714dc10c0142ce0af8c20ec44dc6928ae63ad4f73aHerbert Xu crypto_unregister_ahash(&alg->alg.u.hash); 10724dc10c0142ce0af8c20ec44dc6928ae63ad4f73aHerbert Xu break; 10734dc10c0142ce0af8c20ec44dc6928ae63ad4f73aHerbert Xu 10744dc10c0142ce0af8c20ec44dc6928ae63ad4f73aHerbert Xu default: 10754dc10c0142ce0af8c20ec44dc6928ae63ad4f73aHerbert Xu crypto_unregister_alg(&alg->alg.u.cipher); 10764dc10c0142ce0af8c20ec44dc6928ae63ad4f73aHerbert Xu } 1077049359d655277c382683a6030ae0bac485568ffcJames Hsiao kfree(alg); 1078049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 1079049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 1080049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1081049359d655277c382683a6030ae0bac485568ffcJames Hsiaostatic void crypto4xx_bh_tasklet_cb(unsigned long data) 1082049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 1083049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct device *dev = (struct device *)data; 1084049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct crypto4xx_core_device *core_dev = dev_get_drvdata(dev); 1085049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct pd_uinfo *pd_uinfo; 1086049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct ce_pd *pd; 1087049359d655277c382683a6030ae0bac485568ffcJames Hsiao u32 tail; 1088049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1089049359d655277c382683a6030ae0bac485568ffcJames Hsiao while (core_dev->dev->pdr_head != core_dev->dev->pdr_tail) { 1090049359d655277c382683a6030ae0bac485568ffcJames Hsiao tail = core_dev->dev->pdr_tail; 1091049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd_uinfo = core_dev->dev->pdr_uinfo + 1092049359d655277c382683a6030ae0bac485568ffcJames Hsiao sizeof(struct pd_uinfo)*tail; 1093049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd = core_dev->dev->pdr + sizeof(struct ce_pd) * tail; 1094049359d655277c382683a6030ae0bac485568ffcJames Hsiao if ((pd_uinfo->state == PD_ENTRY_INUSE) && 1095049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd->pd_ctl.bf.pe_done && 1096049359d655277c382683a6030ae0bac485568ffcJames Hsiao !pd->pd_ctl.bf.host_ready) { 1097049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd->pd_ctl.bf.pe_done = 0; 1098049359d655277c382683a6030ae0bac485568ffcJames Hsiao crypto4xx_pd_done(core_dev->dev, tail); 1099049359d655277c382683a6030ae0bac485568ffcJames Hsiao crypto4xx_put_pd_to_pdr(core_dev->dev, tail); 1100049359d655277c382683a6030ae0bac485568ffcJames Hsiao pd_uinfo->state = PD_ENTRY_FREE; 1101049359d655277c382683a6030ae0bac485568ffcJames Hsiao } else { 1102049359d655277c382683a6030ae0bac485568ffcJames Hsiao /* if tail not done, break */ 1103049359d655277c382683a6030ae0bac485568ffcJames Hsiao break; 1104049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 1105049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 1106049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 1107049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1108049359d655277c382683a6030ae0bac485568ffcJames Hsiao/** 1109049359d655277c382683a6030ae0bac485568ffcJames Hsiao * Top Half of isr. 1110049359d655277c382683a6030ae0bac485568ffcJames Hsiao */ 1111049359d655277c382683a6030ae0bac485568ffcJames Hsiaostatic irqreturn_t crypto4xx_ce_interrupt_handler(int irq, void *data) 1112049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 1113049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct device *dev = (struct device *)data; 1114049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct crypto4xx_core_device *core_dev = dev_get_drvdata(dev); 1115049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1116049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (core_dev->dev->ce_base == 0) 1117049359d655277c382683a6030ae0bac485568ffcJames Hsiao return 0; 1118049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1119049359d655277c382683a6030ae0bac485568ffcJames Hsiao writel(PPC4XX_INTERRUPT_CLR, 1120049359d655277c382683a6030ae0bac485568ffcJames Hsiao core_dev->dev->ce_base + CRYPTO4XX_INT_CLR); 1121049359d655277c382683a6030ae0bac485568ffcJames Hsiao tasklet_schedule(&core_dev->tasklet); 1122049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1123049359d655277c382683a6030ae0bac485568ffcJames Hsiao return IRQ_HANDLED; 1124049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 1125049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1126049359d655277c382683a6030ae0bac485568ffcJames Hsiao/** 1127049359d655277c382683a6030ae0bac485568ffcJames Hsiao * Supported Crypto Algorithms 1128049359d655277c382683a6030ae0bac485568ffcJames Hsiao */ 11294dc10c0142ce0af8c20ec44dc6928ae63ad4f73aHerbert Xustruct crypto4xx_alg_common crypto4xx_alg[] = { 1130049359d655277c382683a6030ae0bac485568ffcJames Hsiao /* Crypto AES modes */ 11314dc10c0142ce0af8c20ec44dc6928ae63ad4f73aHerbert Xu { .type = CRYPTO_ALG_TYPE_ABLKCIPHER, .u.cipher = { 1132049359d655277c382683a6030ae0bac485568ffcJames Hsiao .cra_name = "cbc(aes)", 1133049359d655277c382683a6030ae0bac485568ffcJames Hsiao .cra_driver_name = "cbc-aes-ppc4xx", 1134049359d655277c382683a6030ae0bac485568ffcJames Hsiao .cra_priority = CRYPTO4XX_CRYPTO_PRIORITY, 1135049359d655277c382683a6030ae0bac485568ffcJames Hsiao .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, 1136049359d655277c382683a6030ae0bac485568ffcJames Hsiao .cra_blocksize = AES_BLOCK_SIZE, 1137049359d655277c382683a6030ae0bac485568ffcJames Hsiao .cra_ctxsize = sizeof(struct crypto4xx_ctx), 1138049359d655277c382683a6030ae0bac485568ffcJames Hsiao .cra_type = &crypto_ablkcipher_type, 11394dc10c0142ce0af8c20ec44dc6928ae63ad4f73aHerbert Xu .cra_init = crypto4xx_alg_init, 11404dc10c0142ce0af8c20ec44dc6928ae63ad4f73aHerbert Xu .cra_exit = crypto4xx_alg_exit, 1141049359d655277c382683a6030ae0bac485568ffcJames Hsiao .cra_module = THIS_MODULE, 1142049359d655277c382683a6030ae0bac485568ffcJames Hsiao .cra_u = { 1143049359d655277c382683a6030ae0bac485568ffcJames Hsiao .ablkcipher = { 1144049359d655277c382683a6030ae0bac485568ffcJames Hsiao .min_keysize = AES_MIN_KEY_SIZE, 1145049359d655277c382683a6030ae0bac485568ffcJames Hsiao .max_keysize = AES_MAX_KEY_SIZE, 1146049359d655277c382683a6030ae0bac485568ffcJames Hsiao .ivsize = AES_IV_SIZE, 1147049359d655277c382683a6030ae0bac485568ffcJames Hsiao .setkey = crypto4xx_setkey_aes_cbc, 1148049359d655277c382683a6030ae0bac485568ffcJames Hsiao .encrypt = crypto4xx_encrypt, 1149049359d655277c382683a6030ae0bac485568ffcJames Hsiao .decrypt = crypto4xx_decrypt, 1150049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 1151049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 11524dc10c0142ce0af8c20ec44dc6928ae63ad4f73aHerbert Xu }}, 1153049359d655277c382683a6030ae0bac485568ffcJames Hsiao}; 1154049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1155049359d655277c382683a6030ae0bac485568ffcJames Hsiao/** 1156049359d655277c382683a6030ae0bac485568ffcJames Hsiao * Module Initialization Routine 1157049359d655277c382683a6030ae0bac485568ffcJames Hsiao */ 1158000061245a6797d542854106463b6b20fbdcb12eGrant Likelystatic int __init crypto4xx_probe(struct platform_device *ofdev) 1159049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 1160049359d655277c382683a6030ae0bac485568ffcJames Hsiao int rc; 1161049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct resource res; 1162049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct device *dev = &ofdev->dev; 1163049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct crypto4xx_core_device *core_dev; 1164049359d655277c382683a6030ae0bac485568ffcJames Hsiao 11657cea8cc4705d25d9c7baee06efd665db27481242Anatolij Gustschin rc = of_address_to_resource(ofdev->dev.of_node, 0, &res); 1166049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (rc) 1167049359d655277c382683a6030ae0bac485568ffcJames Hsiao return -ENODEV; 1168049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1169049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (of_find_compatible_node(NULL, NULL, "amcc,ppc460ex-crypto")) { 1170049359d655277c382683a6030ae0bac485568ffcJames Hsiao mtdcri(SDR0, PPC460EX_SDR0_SRST, 1171049359d655277c382683a6030ae0bac485568ffcJames Hsiao mfdcri(SDR0, PPC460EX_SDR0_SRST) | PPC460EX_CE_RESET); 1172049359d655277c382683a6030ae0bac485568ffcJames Hsiao mtdcri(SDR0, PPC460EX_SDR0_SRST, 1173049359d655277c382683a6030ae0bac485568ffcJames Hsiao mfdcri(SDR0, PPC460EX_SDR0_SRST) & ~PPC460EX_CE_RESET); 1174049359d655277c382683a6030ae0bac485568ffcJames Hsiao } else if (of_find_compatible_node(NULL, NULL, 1175049359d655277c382683a6030ae0bac485568ffcJames Hsiao "amcc,ppc405ex-crypto")) { 1176049359d655277c382683a6030ae0bac485568ffcJames Hsiao mtdcri(SDR0, PPC405EX_SDR0_SRST, 1177049359d655277c382683a6030ae0bac485568ffcJames Hsiao mfdcri(SDR0, PPC405EX_SDR0_SRST) | PPC405EX_CE_RESET); 1178049359d655277c382683a6030ae0bac485568ffcJames Hsiao mtdcri(SDR0, PPC405EX_SDR0_SRST, 1179049359d655277c382683a6030ae0bac485568ffcJames Hsiao mfdcri(SDR0, PPC405EX_SDR0_SRST) & ~PPC405EX_CE_RESET); 1180049359d655277c382683a6030ae0bac485568ffcJames Hsiao } else if (of_find_compatible_node(NULL, NULL, 1181049359d655277c382683a6030ae0bac485568ffcJames Hsiao "amcc,ppc460sx-crypto")) { 1182049359d655277c382683a6030ae0bac485568ffcJames Hsiao mtdcri(SDR0, PPC460SX_SDR0_SRST, 1183049359d655277c382683a6030ae0bac485568ffcJames Hsiao mfdcri(SDR0, PPC460SX_SDR0_SRST) | PPC460SX_CE_RESET); 1184049359d655277c382683a6030ae0bac485568ffcJames Hsiao mtdcri(SDR0, PPC460SX_SDR0_SRST, 1185049359d655277c382683a6030ae0bac485568ffcJames Hsiao mfdcri(SDR0, PPC460SX_SDR0_SRST) & ~PPC460SX_CE_RESET); 1186049359d655277c382683a6030ae0bac485568ffcJames Hsiao } else { 1187049359d655277c382683a6030ae0bac485568ffcJames Hsiao printk(KERN_ERR "Crypto Function Not supported!\n"); 1188049359d655277c382683a6030ae0bac485568ffcJames Hsiao return -EINVAL; 1189049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 1190049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1191049359d655277c382683a6030ae0bac485568ffcJames Hsiao core_dev = kzalloc(sizeof(struct crypto4xx_core_device), GFP_KERNEL); 1192049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (!core_dev) 1193049359d655277c382683a6030ae0bac485568ffcJames Hsiao return -ENOMEM; 1194049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1195049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev_set_drvdata(dev, core_dev); 1196049359d655277c382683a6030ae0bac485568ffcJames Hsiao core_dev->ofdev = ofdev; 1197049359d655277c382683a6030ae0bac485568ffcJames Hsiao core_dev->dev = kzalloc(sizeof(struct crypto4xx_device), GFP_KERNEL); 1198049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (!core_dev->dev) 1199049359d655277c382683a6030ae0bac485568ffcJames Hsiao goto err_alloc_dev; 1200049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1201049359d655277c382683a6030ae0bac485568ffcJames Hsiao core_dev->dev->core_dev = core_dev; 1202049359d655277c382683a6030ae0bac485568ffcJames Hsiao core_dev->device = dev; 1203049359d655277c382683a6030ae0bac485568ffcJames Hsiao spin_lock_init(&core_dev->lock); 1204049359d655277c382683a6030ae0bac485568ffcJames Hsiao INIT_LIST_HEAD(&core_dev->dev->alg_list); 1205049359d655277c382683a6030ae0bac485568ffcJames Hsiao rc = crypto4xx_build_pdr(core_dev->dev); 1206049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (rc) 1207049359d655277c382683a6030ae0bac485568ffcJames Hsiao goto err_build_pdr; 1208049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1209049359d655277c382683a6030ae0bac485568ffcJames Hsiao rc = crypto4xx_build_gdr(core_dev->dev); 1210049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (rc) 1211049359d655277c382683a6030ae0bac485568ffcJames Hsiao goto err_build_gdr; 1212049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1213049359d655277c382683a6030ae0bac485568ffcJames Hsiao rc = crypto4xx_build_sdr(core_dev->dev); 1214049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (rc) 1215049359d655277c382683a6030ae0bac485568ffcJames Hsiao goto err_build_sdr; 1216049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1217049359d655277c382683a6030ae0bac485568ffcJames Hsiao /* Init tasklet for bottom half processing */ 1218049359d655277c382683a6030ae0bac485568ffcJames Hsiao tasklet_init(&core_dev->tasklet, crypto4xx_bh_tasklet_cb, 1219049359d655277c382683a6030ae0bac485568ffcJames Hsiao (unsigned long) dev); 1220049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1221049359d655277c382683a6030ae0bac485568ffcJames Hsiao /* Register for Crypto isr, Crypto Engine IRQ */ 12227cea8cc4705d25d9c7baee06efd665db27481242Anatolij Gustschin core_dev->irq = irq_of_parse_and_map(ofdev->dev.of_node, 0); 1223049359d655277c382683a6030ae0bac485568ffcJames Hsiao rc = request_irq(core_dev->irq, crypto4xx_ce_interrupt_handler, 0, 1224049359d655277c382683a6030ae0bac485568ffcJames Hsiao core_dev->dev->name, dev); 1225049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (rc) 1226049359d655277c382683a6030ae0bac485568ffcJames Hsiao goto err_request_irq; 1227049359d655277c382683a6030ae0bac485568ffcJames Hsiao 12287cea8cc4705d25d9c7baee06efd665db27481242Anatolij Gustschin core_dev->dev->ce_base = of_iomap(ofdev->dev.of_node, 0); 1229049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (!core_dev->dev->ce_base) { 1230049359d655277c382683a6030ae0bac485568ffcJames Hsiao dev_err(dev, "failed to of_iomap\n"); 1231b48ae1df54b77daa3dc2382b7fd1d980329087bdPeter Senna Tschudin rc = -ENOMEM; 1232049359d655277c382683a6030ae0bac485568ffcJames Hsiao goto err_iomap; 1233049359d655277c382683a6030ae0bac485568ffcJames Hsiao } 1234049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1235049359d655277c382683a6030ae0bac485568ffcJames Hsiao /* need to setup pdr, rdr, gdr and sdr before this */ 1236049359d655277c382683a6030ae0bac485568ffcJames Hsiao crypto4xx_hw_init(core_dev->dev); 1237049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1238049359d655277c382683a6030ae0bac485568ffcJames Hsiao /* Register security algorithms with Linux CryptoAPI */ 1239049359d655277c382683a6030ae0bac485568ffcJames Hsiao rc = crypto4xx_register_alg(core_dev->dev, crypto4xx_alg, 1240049359d655277c382683a6030ae0bac485568ffcJames Hsiao ARRAY_SIZE(crypto4xx_alg)); 1241049359d655277c382683a6030ae0bac485568ffcJames Hsiao if (rc) 1242049359d655277c382683a6030ae0bac485568ffcJames Hsiao goto err_start_dev; 1243049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1244049359d655277c382683a6030ae0bac485568ffcJames Hsiao return 0; 1245049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1246049359d655277c382683a6030ae0bac485568ffcJames Hsiaoerr_start_dev: 1247049359d655277c382683a6030ae0bac485568ffcJames Hsiao iounmap(core_dev->dev->ce_base); 1248049359d655277c382683a6030ae0bac485568ffcJames Hsiaoerr_iomap: 1249049359d655277c382683a6030ae0bac485568ffcJames Hsiao free_irq(core_dev->irq, dev); 1250bdd3f7fa77257a818746caf9fbe0ea0e7bb7dde4Julia Lawallerr_request_irq: 1251049359d655277c382683a6030ae0bac485568ffcJames Hsiao irq_dispose_mapping(core_dev->irq); 1252049359d655277c382683a6030ae0bac485568ffcJames Hsiao tasklet_kill(&core_dev->tasklet); 1253049359d655277c382683a6030ae0bac485568ffcJames Hsiao crypto4xx_destroy_sdr(core_dev->dev); 1254049359d655277c382683a6030ae0bac485568ffcJames Hsiaoerr_build_sdr: 1255049359d655277c382683a6030ae0bac485568ffcJames Hsiao crypto4xx_destroy_gdr(core_dev->dev); 1256049359d655277c382683a6030ae0bac485568ffcJames Hsiaoerr_build_gdr: 1257049359d655277c382683a6030ae0bac485568ffcJames Hsiao crypto4xx_destroy_pdr(core_dev->dev); 1258049359d655277c382683a6030ae0bac485568ffcJames Hsiaoerr_build_pdr: 1259049359d655277c382683a6030ae0bac485568ffcJames Hsiao kfree(core_dev->dev); 1260049359d655277c382683a6030ae0bac485568ffcJames Hsiaoerr_alloc_dev: 1261049359d655277c382683a6030ae0bac485568ffcJames Hsiao kfree(core_dev); 1262049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1263049359d655277c382683a6030ae0bac485568ffcJames Hsiao return rc; 1264049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 1265049359d655277c382683a6030ae0bac485568ffcJames Hsiao 12662dc11581376829303b98eadb2de253bee065a56aGrant Likelystatic int __exit crypto4xx_remove(struct platform_device *ofdev) 1267049359d655277c382683a6030ae0bac485568ffcJames Hsiao{ 1268049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct device *dev = &ofdev->dev; 1269049359d655277c382683a6030ae0bac485568ffcJames Hsiao struct crypto4xx_core_device *core_dev = dev_get_drvdata(dev); 1270049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1271049359d655277c382683a6030ae0bac485568ffcJames Hsiao free_irq(core_dev->irq, dev); 1272049359d655277c382683a6030ae0bac485568ffcJames Hsiao irq_dispose_mapping(core_dev->irq); 1273049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1274049359d655277c382683a6030ae0bac485568ffcJames Hsiao tasklet_kill(&core_dev->tasklet); 1275049359d655277c382683a6030ae0bac485568ffcJames Hsiao /* Un-register with Linux CryptoAPI */ 1276049359d655277c382683a6030ae0bac485568ffcJames Hsiao crypto4xx_unregister_alg(core_dev->dev); 1277049359d655277c382683a6030ae0bac485568ffcJames Hsiao /* Free all allocated memory */ 1278049359d655277c382683a6030ae0bac485568ffcJames Hsiao crypto4xx_stop_all(core_dev); 1279049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1280049359d655277c382683a6030ae0bac485568ffcJames Hsiao return 0; 1281049359d655277c382683a6030ae0bac485568ffcJames Hsiao} 1282049359d655277c382683a6030ae0bac485568ffcJames Hsiao 12836c3f975a4cafaf4dcc9795385da6d42caa37ddebMárton Némethstatic const struct of_device_id crypto4xx_match[] = { 1284049359d655277c382683a6030ae0bac485568ffcJames Hsiao { .compatible = "amcc,ppc4xx-crypto",}, 1285049359d655277c382683a6030ae0bac485568ffcJames Hsiao { }, 1286049359d655277c382683a6030ae0bac485568ffcJames Hsiao}; 1287049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1288000061245a6797d542854106463b6b20fbdcb12eGrant Likelystatic struct platform_driver crypto4xx_driver = { 12894018294b53d1dae026880e45f174c1cc63b5d435Grant Likely .driver = { 12904018294b53d1dae026880e45f174c1cc63b5d435Grant Likely .name = "crypto4xx", 12914018294b53d1dae026880e45f174c1cc63b5d435Grant Likely .owner = THIS_MODULE, 12924018294b53d1dae026880e45f174c1cc63b5d435Grant Likely .of_match_table = crypto4xx_match, 12934018294b53d1dae026880e45f174c1cc63b5d435Grant Likely }, 1294049359d655277c382683a6030ae0bac485568ffcJames Hsiao .probe = crypto4xx_probe, 129513269ec647050fd7652abd0eb05673ffe90c3e92Jean Delvare .remove = __exit_p(crypto4xx_remove), 1296049359d655277c382683a6030ae0bac485568ffcJames Hsiao}; 1297049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1298741e8c2d8177eca656bc015ef83ab84d817edf8cAxel Linmodule_platform_driver(crypto4xx_driver); 1299049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1300049359d655277c382683a6030ae0bac485568ffcJames HsiaoMODULE_LICENSE("GPL"); 1301049359d655277c382683a6030ae0bac485568ffcJames HsiaoMODULE_AUTHOR("James Hsiao <jhsiao@amcc.com>"); 1302049359d655277c382683a6030ae0bac485568ffcJames HsiaoMODULE_DESCRIPTION("Driver for AMCC PPC4xx crypto accelerator"); 1303049359d655277c382683a6030ae0bac485568ffcJames Hsiao 1304