1/* Copyright (c) 2013,2015, The Linux Foundation. All rights reserved. 2 * 3 * Permission to use, copy, modify, and/or distribute this software for any 4 * purpose with or without fee is hereby granted, provided that the above 5 * copyright notice and this permission notice appear in all copies. 6 * 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT 11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14 * PERFORMANCE OF THIS SOFTWARE. 15 * 16 * 17 */ 18#include <linux/types.h> 19#include <linux/kernel.h> 20#include <linux/module.h> 21#include <linux/slab.h> 22#include <linux/device.h> 23#include <linux/memory.h> 24#include <linux/io.h> 25#include <linux/clk.h> 26#include <linux/uaccess.h> 27#include <linux/dma-mapping.h> 28#include <linux/platform_device.h> 29#include <mach/msm_iomap.h> 30#include <mach/msm_nss_crypto.h> 31#include <linux/interrupt.h> 32#include <linux/delay.h> 33#include <linux/vmalloc.h> 34#include <nss_crypto_hlos.h> 35#include <nss_api_if.h> 36#include <nss_crypto.h> 37#include <nss_crypto_if.h> 38#include <nss_crypto_hw.h> 39#include <nss_crypto_ctrl.h> 40#include <nss_crypto_dbg.h> 41#include <nss_crypto_debugfs.h> 42 43#define REG(off) (MSM_CLK_CTL_BASE + (off)) 44#define REG_GCC(off) (MSM_APCS_GCC_BASE + (off)) 45 46#define CRYPTO_RESET_ENG(n) REG(0x3E00 + (n * 0x4)) 47#define CRYPTO_RESET_AHB REG(0x3E10) 48 49#define CRYPTO_RESET_ENG_0 REG(0x3E00) 50#define CRYPTO_RESET_ENG_1 REG(0x3E04) 51#define CRYPTO_RESET_ENG_2 REG(0x3E08) 52#define CRYPTO_RESET_ENG_3 REG(0x3E0C) 53 54/* Poll time in ms */ 55#define CRYPTO_DELAYED_INIT_TIME 100 56 57extern struct nss_crypto_ctrl gbl_crypto_ctrl; 58extern struct nss_ctx_instance *nss_drv_hdl; 59 60static int eng_count; 61 62void nss_crypto_engine_init(uint32_t eng_count); 63void nss_crypto_init(void); 64 65/* 66 * nss_crypto_bam_init() 67 * initialize the BAM for the given engine 68 */ 69static void nss_crypto_bam_init(uint8_t *bam_iobase) 70{ 71 uint32_t cfg_bits; 72 uint32_t ctrl_reg; 73 74 ctrl_reg = ioread32(bam_iobase + CRYPTO_BAM_CTRL); 75 76 ctrl_reg |= CRYPTO_BAM_CTRL_SW_RST; 77 iowrite32(ctrl_reg, bam_iobase + CRYPTO_BAM_CTRL); 78 79 ctrl_reg &= ~CRYPTO_BAM_CTRL_SW_RST; 80 iowrite32(ctrl_reg, bam_iobase + CRYPTO_BAM_CTRL); 81 82 ctrl_reg |= CRYPTO_BAM_CTRL_BAM_EN; 83 iowrite32(ctrl_reg, bam_iobase + CRYPTO_BAM_CTRL); 84 85 iowrite32(CRYPTO_BAM_DESC_CNT_TRSHLD_VAL, bam_iobase + CRYPTO_BAM_DESC_CNT_TRSHLD); 86 87 /* disabling this is recommended from H/W specification*/ 88 cfg_bits = ~((uint32_t)CRYPTO_BAM_CNFG_BITS_BAM_FULL_PIPE); 89 iowrite32(cfg_bits, bam_iobase + CRYPTO_BAM_CNFG_BITS); 90} 91 92/* 93 * nss_crypto_probe() 94 * probe routine called per engine from MACH-MSM 95 */ 96static int nss_crypto_probe(struct platform_device *pdev) 97{ 98 struct nss_crypto_ctrl_eng *e_ctrl; 99 struct nss_crypto_platform_data *res; 100 struct nss_crypto_ctrl_eng *eng_ptr; 101 int status = 0; 102 size_t old_sz; 103 size_t new_sz; 104 105 nss_crypto_info_always("probing engine - %d\n", eng_count); 106 nss_crypto_assert(eng_count < NSS_CRYPTO_MAX_ENGINES); 107 108 eng_ptr = gbl_crypto_ctrl.eng; 109 110 old_sz = (gbl_crypto_ctrl.num_eng * sizeof(struct nss_crypto_ctrl_eng)); 111 new_sz = old_sz + sizeof(struct nss_crypto_ctrl_eng); 112 113 eng_ptr = nss_crypto_mem_realloc(eng_ptr, old_sz, new_sz); 114 if (eng_ptr == NULL) { 115 return -ENOMEM; 116 } 117 118 gbl_crypto_ctrl.eng = eng_ptr; 119 120 e_ctrl = &gbl_crypto_ctrl.eng[eng_count]; 121 e_ctrl->dev = &pdev->dev; 122 123 /* crypto engine resources */ 124 res = dev_get_platdata(e_ctrl->dev); 125 nss_crypto_assert(res); 126 127 e_ctrl->bam_ee = res->bam_ee; 128 129 e_ctrl->cmd_base = res->crypto_pbase; 130 e_ctrl->crypto_base = ioremap_nocache(res->crypto_pbase, res->crypto_pbase_sz); 131 nss_crypto_assert(e_ctrl->crypto_base); 132 133 e_ctrl->bam_pbase = res->bam_pbase; 134 e_ctrl->bam_base = ioremap_nocache(res->bam_pbase, res->bam_pbase_sz); 135 nss_crypto_assert(e_ctrl->bam_base); 136 137 /* 138 * Link address of engine ctrl 139 */ 140 platform_set_drvdata(pdev, e_ctrl); 141 142 /* 143 * intialize the BAM and the engine 144 */ 145 nss_crypto_bam_init(e_ctrl->bam_base); 146 nss_crypto_engine_init(eng_count); 147 148 eng_count++; 149 gbl_crypto_ctrl.num_eng = eng_count; 150 151 return status; 152} 153 154/* 155 * nss_crypto_remove() 156 * remove the crypto engine and deregister everything 157 */ 158static int nss_crypto_remove(struct platform_device *pdev) 159{ 160 struct nss_crypto_ctrl_eng *ctrl; 161 162 ctrl = platform_get_drvdata(pdev); 163 164 /** 165 * XXX: pipe deinit goes here 166 */ 167 return 0; 168}; 169 170/* 171 * platform device instance 172 */ 173static struct platform_driver nss_crypto_drv = { 174 .probe = nss_crypto_probe, 175 .remove = nss_crypto_remove, 176 .driver = { 177 .owner = THIS_MODULE, 178 .name = "nss-crypto", 179 }, 180}; 181 182/* 183 * nss_crypto_module_exit() 184 * module exit for crypto driver 185 */ 186static void __exit nss_crypto_module_exit(void) 187{ 188 nss_crypto_info("module unloaded (IPQ806x)\n"); 189 190 platform_driver_unregister(&nss_crypto_drv); 191} 192 193void nss_crypto_delayed_init(struct work_struct *work) 194{ 195 struct nss_crypto_ctrl *ctrl; 196 uint32_t status = 0; 197 uint32_t i = 0; 198 199 ctrl = container_of(to_delayed_work(work), struct nss_crypto_ctrl, crypto_work); 200 201 /* 202 * check if NSS FW is initialized 203 */ 204 if (nss_get_state(nss_drv_hdl) != NSS_STATE_INITIALIZED) { 205 schedule_delayed_work(&ctrl->crypto_work, msecs_to_jiffies(CRYPTO_DELAYED_INIT_TIME)); 206 return; 207 } 208 209 nss_crypto_info_always("NSS Firmware initialized\n"); 210 211 /* 212 * reserve the index if certain pipe pairs are locked out for 213 * trust zone use 214 */ 215 ctrl->idx_bitmap = 0; 216 217 status = platform_driver_register(&nss_crypto_drv); 218 if (status != 0) { 219 nss_crypto_err("unable to register the driver : %d\n", status); 220 return; 221 } 222 223 /* 224 * Initialize the engine stats 225 */ 226 for (i = 0; i < gbl_crypto_ctrl.num_eng ; i++) 227 nss_crypto_debugfs_add_engine(ctrl, i); 228} 229 230/* 231 * nss_crypto_module_init() 232 * module init for crypto driver 233 */ 234static int __init nss_crypto_module_init(void) 235{ 236 237 nss_crypto_info("module loaded (platform - IPQ806x, build - %s:%s)\n", __DATE__, __TIME__); 238 239 /* 240 * bring the crypto out of reset 241 */ 242 iowrite32(0, CRYPTO_RESET_ENG(0)); 243 iowrite32(0, CRYPTO_RESET_ENG(1)); 244 iowrite32(0, CRYPTO_RESET_ENG(2)); 245 iowrite32(0, CRYPTO_RESET_ENG(3)); 246 247 iowrite32(0, CRYPTO_RESET_AHB); 248 249 nss_crypto_init(); 250 251 nss_crypto_info_always("Register with NSS driver-\n"); 252 253 INIT_DELAYED_WORK(&gbl_crypto_ctrl.crypto_work, nss_crypto_delayed_init); 254 255 schedule_delayed_work(&gbl_crypto_ctrl.crypto_work, msecs_to_jiffies(CRYPTO_DELAYED_INIT_TIME)); 256 257 return 0; 258} 259 260module_init(nss_crypto_module_init); 261module_exit(nss_crypto_module_exit); 262 263MODULE_LICENSE("Dual BSD/GPL"); 264MODULE_DESCRIPTION("QCA NSS Crypto driver"); 265MODULE_AUTHOR("Qualcomm Atheros Inc"); 266