1/* 2 * sun4i-ss-core.c - hardware cryptographic accelerator for Allwinner A20 SoC 3 * 4 * Copyright (C) 2013-2015 Corentin LABBE <clabbe.montjoie@gmail.com> 5 * 6 * Core file which registers crypto algorithms supported by the SS. 7 * 8 * You could find a link for the datasheet in Documentation/arm/sunxi/README 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 */ 15#include <linux/clk.h> 16#include <linux/crypto.h> 17#include <linux/io.h> 18#include <linux/module.h> 19#include <linux/of.h> 20#include <linux/platform_device.h> 21#include <crypto/scatterwalk.h> 22#include <linux/scatterlist.h> 23#include <linux/interrupt.h> 24#include <linux/delay.h> 25#include <linux/reset.h> 26 27#include "sun4i-ss.h" 28 29static struct sun4i_ss_alg_template ss_algs[] = { 30{ .type = CRYPTO_ALG_TYPE_AHASH, 31 .mode = SS_OP_MD5, 32 .alg.hash = { 33 .init = sun4i_hash_init, 34 .update = sun4i_hash_update, 35 .final = sun4i_hash_final, 36 .finup = sun4i_hash_finup, 37 .digest = sun4i_hash_digest, 38 .export = sun4i_hash_export_md5, 39 .import = sun4i_hash_import_md5, 40 .halg = { 41 .digestsize = MD5_DIGEST_SIZE, 42 .statesize = sizeof(struct md5_state), 43 .base = { 44 .cra_name = "md5", 45 .cra_driver_name = "md5-sun4i-ss", 46 .cra_priority = 300, 47 .cra_alignmask = 3, 48 .cra_flags = CRYPTO_ALG_TYPE_AHASH, 49 .cra_blocksize = MD5_HMAC_BLOCK_SIZE, 50 .cra_ctxsize = sizeof(struct sun4i_req_ctx), 51 .cra_module = THIS_MODULE, 52 .cra_type = &crypto_ahash_type, 53 .cra_init = sun4i_hash_crainit 54 } 55 } 56 } 57}, 58{ .type = CRYPTO_ALG_TYPE_AHASH, 59 .mode = SS_OP_SHA1, 60 .alg.hash = { 61 .init = sun4i_hash_init, 62 .update = sun4i_hash_update, 63 .final = sun4i_hash_final, 64 .finup = sun4i_hash_finup, 65 .digest = sun4i_hash_digest, 66 .export = sun4i_hash_export_sha1, 67 .import = sun4i_hash_import_sha1, 68 .halg = { 69 .digestsize = SHA1_DIGEST_SIZE, 70 .statesize = sizeof(struct sha1_state), 71 .base = { 72 .cra_name = "sha1", 73 .cra_driver_name = "sha1-sun4i-ss", 74 .cra_priority = 300, 75 .cra_alignmask = 3, 76 .cra_flags = CRYPTO_ALG_TYPE_AHASH, 77 .cra_blocksize = SHA1_BLOCK_SIZE, 78 .cra_ctxsize = sizeof(struct sun4i_req_ctx), 79 .cra_module = THIS_MODULE, 80 .cra_type = &crypto_ahash_type, 81 .cra_init = sun4i_hash_crainit 82 } 83 } 84 } 85}, 86{ .type = CRYPTO_ALG_TYPE_ABLKCIPHER, 87 .alg.crypto = { 88 .cra_name = "cbc(aes)", 89 .cra_driver_name = "cbc-aes-sun4i-ss", 90 .cra_priority = 300, 91 .cra_blocksize = AES_BLOCK_SIZE, 92 .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER, 93 .cra_ctxsize = sizeof(struct sun4i_tfm_ctx), 94 .cra_module = THIS_MODULE, 95 .cra_alignmask = 3, 96 .cra_type = &crypto_ablkcipher_type, 97 .cra_init = sun4i_ss_cipher_init, 98 .cra_ablkcipher = { 99 .min_keysize = AES_MIN_KEY_SIZE, 100 .max_keysize = AES_MAX_KEY_SIZE, 101 .ivsize = AES_BLOCK_SIZE, 102 .setkey = sun4i_ss_aes_setkey, 103 .encrypt = sun4i_ss_cbc_aes_encrypt, 104 .decrypt = sun4i_ss_cbc_aes_decrypt, 105 } 106 } 107}, 108{ .type = CRYPTO_ALG_TYPE_ABLKCIPHER, 109 .alg.crypto = { 110 .cra_name = "ecb(aes)", 111 .cra_driver_name = "ecb-aes-sun4i-ss", 112 .cra_priority = 300, 113 .cra_blocksize = AES_BLOCK_SIZE, 114 .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER, 115 .cra_ctxsize = sizeof(struct sun4i_tfm_ctx), 116 .cra_module = THIS_MODULE, 117 .cra_alignmask = 3, 118 .cra_type = &crypto_ablkcipher_type, 119 .cra_init = sun4i_ss_cipher_init, 120 .cra_ablkcipher = { 121 .min_keysize = AES_MIN_KEY_SIZE, 122 .max_keysize = AES_MAX_KEY_SIZE, 123 .ivsize = AES_BLOCK_SIZE, 124 .setkey = sun4i_ss_aes_setkey, 125 .encrypt = sun4i_ss_ecb_aes_encrypt, 126 .decrypt = sun4i_ss_ecb_aes_decrypt, 127 } 128 } 129}, 130{ .type = CRYPTO_ALG_TYPE_ABLKCIPHER, 131 .alg.crypto = { 132 .cra_name = "cbc(des)", 133 .cra_driver_name = "cbc-des-sun4i-ss", 134 .cra_priority = 300, 135 .cra_blocksize = DES_BLOCK_SIZE, 136 .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER, 137 .cra_ctxsize = sizeof(struct sun4i_req_ctx), 138 .cra_module = THIS_MODULE, 139 .cra_alignmask = 3, 140 .cra_type = &crypto_ablkcipher_type, 141 .cra_init = sun4i_ss_cipher_init, 142 .cra_u.ablkcipher = { 143 .min_keysize = DES_KEY_SIZE, 144 .max_keysize = DES_KEY_SIZE, 145 .ivsize = DES_BLOCK_SIZE, 146 .setkey = sun4i_ss_des_setkey, 147 .encrypt = sun4i_ss_cbc_des_encrypt, 148 .decrypt = sun4i_ss_cbc_des_decrypt, 149 } 150 } 151}, 152{ .type = CRYPTO_ALG_TYPE_ABLKCIPHER, 153 .alg.crypto = { 154 .cra_name = "ecb(des)", 155 .cra_driver_name = "ecb-des-sun4i-ss", 156 .cra_priority = 300, 157 .cra_blocksize = DES_BLOCK_SIZE, 158 .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER, 159 .cra_ctxsize = sizeof(struct sun4i_req_ctx), 160 .cra_module = THIS_MODULE, 161 .cra_alignmask = 3, 162 .cra_type = &crypto_ablkcipher_type, 163 .cra_init = sun4i_ss_cipher_init, 164 .cra_u.ablkcipher = { 165 .min_keysize = DES_KEY_SIZE, 166 .max_keysize = DES_KEY_SIZE, 167 .setkey = sun4i_ss_des_setkey, 168 .encrypt = sun4i_ss_ecb_des_encrypt, 169 .decrypt = sun4i_ss_ecb_des_decrypt, 170 } 171 } 172}, 173{ .type = CRYPTO_ALG_TYPE_ABLKCIPHER, 174 .alg.crypto = { 175 .cra_name = "cbc(des3_ede)", 176 .cra_driver_name = "cbc-des3-sun4i-ss", 177 .cra_priority = 300, 178 .cra_blocksize = DES3_EDE_BLOCK_SIZE, 179 .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER, 180 .cra_ctxsize = sizeof(struct sun4i_req_ctx), 181 .cra_module = THIS_MODULE, 182 .cra_alignmask = 3, 183 .cra_type = &crypto_ablkcipher_type, 184 .cra_init = sun4i_ss_cipher_init, 185 .cra_u.ablkcipher = { 186 .min_keysize = DES3_EDE_KEY_SIZE, 187 .max_keysize = DES3_EDE_KEY_SIZE, 188 .ivsize = DES3_EDE_BLOCK_SIZE, 189 .setkey = sun4i_ss_des3_setkey, 190 .encrypt = sun4i_ss_cbc_des3_encrypt, 191 .decrypt = sun4i_ss_cbc_des3_decrypt, 192 } 193 } 194}, 195{ .type = CRYPTO_ALG_TYPE_ABLKCIPHER, 196 .alg.crypto = { 197 .cra_name = "ecb(des3_ede)", 198 .cra_driver_name = "ecb-des3-sun4i-ss", 199 .cra_priority = 300, 200 .cra_blocksize = DES3_EDE_BLOCK_SIZE, 201 .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER, 202 .cra_ctxsize = sizeof(struct sun4i_req_ctx), 203 .cra_module = THIS_MODULE, 204 .cra_alignmask = 3, 205 .cra_type = &crypto_ablkcipher_type, 206 .cra_init = sun4i_ss_cipher_init, 207 .cra_u.ablkcipher = { 208 .min_keysize = DES3_EDE_KEY_SIZE, 209 .max_keysize = DES3_EDE_KEY_SIZE, 210 .ivsize = DES3_EDE_BLOCK_SIZE, 211 .setkey = sun4i_ss_des3_setkey, 212 .encrypt = sun4i_ss_ecb_des3_encrypt, 213 .decrypt = sun4i_ss_ecb_des3_decrypt, 214 } 215 } 216}, 217}; 218 219static int sun4i_ss_probe(struct platform_device *pdev) 220{ 221 struct resource *res; 222 u32 v; 223 int err, i; 224 unsigned long cr; 225 const unsigned long cr_ahb = 24 * 1000 * 1000; 226 const unsigned long cr_mod = 150 * 1000 * 1000; 227 struct sun4i_ss_ctx *ss; 228 229 if (!pdev->dev.of_node) 230 return -ENODEV; 231 232 ss = devm_kzalloc(&pdev->dev, sizeof(*ss), GFP_KERNEL); 233 if (!ss) 234 return -ENOMEM; 235 236 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 237 ss->base = devm_ioremap_resource(&pdev->dev, res); 238 if (IS_ERR(ss->base)) { 239 dev_err(&pdev->dev, "Cannot request MMIO\n"); 240 return PTR_ERR(ss->base); 241 } 242 243 ss->ssclk = devm_clk_get(&pdev->dev, "mod"); 244 if (IS_ERR(ss->ssclk)) { 245 err = PTR_ERR(ss->ssclk); 246 dev_err(&pdev->dev, "Cannot get SS clock err=%d\n", err); 247 return err; 248 } 249 dev_dbg(&pdev->dev, "clock ss acquired\n"); 250 251 ss->busclk = devm_clk_get(&pdev->dev, "ahb"); 252 if (IS_ERR(ss->busclk)) { 253 err = PTR_ERR(ss->busclk); 254 dev_err(&pdev->dev, "Cannot get AHB SS clock err=%d\n", err); 255 return err; 256 } 257 dev_dbg(&pdev->dev, "clock ahb_ss acquired\n"); 258 259 ss->reset = devm_reset_control_get_optional(&pdev->dev, "ahb"); 260 if (IS_ERR(ss->reset)) { 261 if (PTR_ERR(ss->reset) == -EPROBE_DEFER) 262 return PTR_ERR(ss->reset); 263 dev_info(&pdev->dev, "no reset control found\n"); 264 ss->reset = NULL; 265 } 266 267 /* Enable both clocks */ 268 err = clk_prepare_enable(ss->busclk); 269 if (err != 0) { 270 dev_err(&pdev->dev, "Cannot prepare_enable busclk\n"); 271 return err; 272 } 273 err = clk_prepare_enable(ss->ssclk); 274 if (err != 0) { 275 dev_err(&pdev->dev, "Cannot prepare_enable ssclk\n"); 276 goto error_ssclk; 277 } 278 279 /* 280 * Check that clock have the correct rates given in the datasheet 281 * Try to set the clock to the maximum allowed 282 */ 283 err = clk_set_rate(ss->ssclk, cr_mod); 284 if (err != 0) { 285 dev_err(&pdev->dev, "Cannot set clock rate to ssclk\n"); 286 goto error_clk; 287 } 288 289 /* Deassert reset if we have a reset control */ 290 if (ss->reset) { 291 err = reset_control_deassert(ss->reset); 292 if (err) { 293 dev_err(&pdev->dev, "Cannot deassert reset control\n"); 294 goto error_clk; 295 } 296 } 297 298 /* 299 * The only impact on clocks below requirement are bad performance, 300 * so do not print "errors" 301 * warn on Overclocked clocks 302 */ 303 cr = clk_get_rate(ss->busclk); 304 if (cr >= cr_ahb) 305 dev_dbg(&pdev->dev, "Clock bus %lu (%lu MHz) (must be >= %lu)\n", 306 cr, cr / 1000000, cr_ahb); 307 else 308 dev_warn(&pdev->dev, "Clock bus %lu (%lu MHz) (must be >= %lu)\n", 309 cr, cr / 1000000, cr_ahb); 310 311 cr = clk_get_rate(ss->ssclk); 312 if (cr <= cr_mod) 313 if (cr < cr_mod) 314 dev_warn(&pdev->dev, "Clock ss %lu (%lu MHz) (must be <= %lu)\n", 315 cr, cr / 1000000, cr_mod); 316 else 317 dev_dbg(&pdev->dev, "Clock ss %lu (%lu MHz) (must be <= %lu)\n", 318 cr, cr / 1000000, cr_mod); 319 else 320 dev_warn(&pdev->dev, "Clock ss is at %lu (%lu MHz) (must be <= %lu)\n", 321 cr, cr / 1000000, cr_mod); 322 323 /* 324 * Datasheet named it "Die Bonding ID" 325 * I expect to be a sort of Security System Revision number. 326 * Since the A80 seems to have an other version of SS 327 * this info could be useful 328 */ 329 writel(SS_ENABLED, ss->base + SS_CTL); 330 v = readl(ss->base + SS_CTL); 331 v >>= 16; 332 v &= 0x07; 333 dev_info(&pdev->dev, "Die ID %d\n", v); 334 writel(0, ss->base + SS_CTL); 335 336 ss->dev = &pdev->dev; 337 338 spin_lock_init(&ss->slock); 339 340 for (i = 0; i < ARRAY_SIZE(ss_algs); i++) { 341 ss_algs[i].ss = ss; 342 switch (ss_algs[i].type) { 343 case CRYPTO_ALG_TYPE_ABLKCIPHER: 344 err = crypto_register_alg(&ss_algs[i].alg.crypto); 345 if (err != 0) { 346 dev_err(ss->dev, "Fail to register %s\n", 347 ss_algs[i].alg.crypto.cra_name); 348 goto error_alg; 349 } 350 break; 351 case CRYPTO_ALG_TYPE_AHASH: 352 err = crypto_register_ahash(&ss_algs[i].alg.hash); 353 if (err != 0) { 354 dev_err(ss->dev, "Fail to register %s\n", 355 ss_algs[i].alg.hash.halg.base.cra_name); 356 goto error_alg; 357 } 358 break; 359 } 360 } 361 platform_set_drvdata(pdev, ss); 362 return 0; 363error_alg: 364 i--; 365 for (; i >= 0; i--) { 366 switch (ss_algs[i].type) { 367 case CRYPTO_ALG_TYPE_ABLKCIPHER: 368 crypto_unregister_alg(&ss_algs[i].alg.crypto); 369 break; 370 case CRYPTO_ALG_TYPE_AHASH: 371 crypto_unregister_ahash(&ss_algs[i].alg.hash); 372 break; 373 } 374 } 375 if (ss->reset) 376 reset_control_assert(ss->reset); 377error_clk: 378 clk_disable_unprepare(ss->ssclk); 379error_ssclk: 380 clk_disable_unprepare(ss->busclk); 381 return err; 382} 383 384static int sun4i_ss_remove(struct platform_device *pdev) 385{ 386 int i; 387 struct sun4i_ss_ctx *ss = platform_get_drvdata(pdev); 388 389 for (i = 0; i < ARRAY_SIZE(ss_algs); i++) { 390 switch (ss_algs[i].type) { 391 case CRYPTO_ALG_TYPE_ABLKCIPHER: 392 crypto_unregister_alg(&ss_algs[i].alg.crypto); 393 break; 394 case CRYPTO_ALG_TYPE_AHASH: 395 crypto_unregister_ahash(&ss_algs[i].alg.hash); 396 break; 397 } 398 } 399 400 writel(0, ss->base + SS_CTL); 401 if (ss->reset) 402 reset_control_assert(ss->reset); 403 clk_disable_unprepare(ss->busclk); 404 clk_disable_unprepare(ss->ssclk); 405 return 0; 406} 407 408static const struct of_device_id a20ss_crypto_of_match_table[] = { 409 { .compatible = "allwinner,sun4i-a10-crypto" }, 410 {} 411}; 412MODULE_DEVICE_TABLE(of, a20ss_crypto_of_match_table); 413 414static struct platform_driver sun4i_ss_driver = { 415 .probe = sun4i_ss_probe, 416 .remove = sun4i_ss_remove, 417 .driver = { 418 .name = "sun4i-ss", 419 .of_match_table = a20ss_crypto_of_match_table, 420 }, 421}; 422 423module_platform_driver(sun4i_ss_driver); 424 425MODULE_DESCRIPTION("Allwinner Security System cryptographic accelerator"); 426MODULE_LICENSE("GPL"); 427MODULE_AUTHOR("Corentin LABBE <clabbe.montjoie@gmail.com>"); 428