mirror of
https://github.com/Ysurac/openmptcprouter.git
synced 2025-03-09 15:40:20 +00:00
插入补丁
This commit is contained in:
parent
3f05dddd16
commit
2353e2efe0
38 changed files with 6702 additions and 0 deletions
|
@ -0,0 +1,31 @@
|
||||||
|
From: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||||
|
Subject: [PATCH] crypto: qce - add CRYPTO_ALG_KERN_DRIVER_ONLY flag
|
||||||
|
|
||||||
|
Set the CRYPTO_ALG_KERN_DRIVER_ONLY flag to all algorithms exposed by
|
||||||
|
the qce driver, since they are all hardware accelerated, accessible
|
||||||
|
through a kernel driver only, and not available directly to userspace.
|
||||||
|
|
||||||
|
Signed-off-by: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||||
|
|
||||||
|
--- a/drivers/crypto/qce/ablkcipher.c
|
||||||
|
+++ b/drivers/crypto/qce/ablkcipher.c
|
||||||
|
@@ -380,7 +380,7 @@ static int qce_ablkcipher_register_one(c
|
||||||
|
|
||||||
|
alg->cra_priority = 300;
|
||||||
|
alg->cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC |
|
||||||
|
- CRYPTO_ALG_NEED_FALLBACK;
|
||||||
|
+ CRYPTO_ALG_NEED_FALLBACK | CRYPTO_ALG_KERN_DRIVER_ONLY;
|
||||||
|
alg->cra_ctxsize = sizeof(struct qce_cipher_ctx);
|
||||||
|
alg->cra_alignmask = 0;
|
||||||
|
alg->cra_type = &crypto_ablkcipher_type;
|
||||||
|
--- a/drivers/crypto/qce/sha.c
|
||||||
|
+++ b/drivers/crypto/qce/sha.c
|
||||||
|
@@ -495,7 +495,7 @@ static int qce_ahash_register_one(const
|
||||||
|
base = &alg->halg.base;
|
||||||
|
base->cra_blocksize = def->blocksize;
|
||||||
|
base->cra_priority = 300;
|
||||||
|
- base->cra_flags = CRYPTO_ALG_ASYNC;
|
||||||
|
+ base->cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY;
|
||||||
|
base->cra_ctxsize = sizeof(struct qce_sha_ctx);
|
||||||
|
base->cra_alignmask = 0;
|
||||||
|
base->cra_module = THIS_MODULE;
|
|
@ -0,0 +1,993 @@
|
||||||
|
From f441873642eebf20566c18d2966a8cd4b433ec1c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ard Biesheuvel <ardb@kernel.org>
|
||||||
|
Date: Tue, 5 Nov 2019 14:28:17 +0100
|
||||||
|
Subject: [PATCH] crypto: qce - switch to skcipher API
|
||||||
|
|
||||||
|
Commit 7a7ffe65c8c5 ("crypto: skcipher - Add top-level skcipher interface")
|
||||||
|
dated 20 august 2015 introduced the new skcipher API which is supposed to
|
||||||
|
replace both blkcipher and ablkcipher. While all consumers of the API have
|
||||||
|
been converted long ago, some producers of the ablkcipher remain, forcing
|
||||||
|
us to keep the ablkcipher support routines alive, along with the matching
|
||||||
|
code to expose [a]blkciphers via the skcipher API.
|
||||||
|
|
||||||
|
So switch this driver to the skcipher API, allowing us to finally drop the
|
||||||
|
blkcipher code in the near future.
|
||||||
|
|
||||||
|
Reviewed-by: Stanimir Varbanov <stanimir.varbanov@linaro.org>
|
||||||
|
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
|
||||||
|
Backported-to-4.19-by: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||||
|
|
||||||
|
--- a/drivers/crypto/qce/Makefile
|
||||||
|
+++ b/drivers/crypto/qce/Makefile
|
||||||
|
@@ -4,4 +4,4 @@ qcrypto-objs := core.o \
|
||||||
|
common.o \
|
||||||
|
dma.o \
|
||||||
|
sha.o \
|
||||||
|
- ablkcipher.o
|
||||||
|
+ skcipher.o
|
||||||
|
--- a/drivers/crypto/qce/cipher.h
|
||||||
|
+++ b/drivers/crypto/qce/cipher.h
|
||||||
|
@@ -45,12 +45,12 @@ struct qce_cipher_reqctx {
|
||||||
|
unsigned int cryptlen;
|
||||||
|
};
|
||||||
|
|
||||||
|
-static inline struct qce_alg_template *to_cipher_tmpl(struct crypto_tfm *tfm)
|
||||||
|
+static inline struct qce_alg_template *to_cipher_tmpl(struct crypto_skcipher *tfm)
|
||||||
|
{
|
||||||
|
- struct crypto_alg *alg = tfm->__crt_alg;
|
||||||
|
- return container_of(alg, struct qce_alg_template, alg.crypto);
|
||||||
|
+ struct skcipher_alg *alg = crypto_skcipher_alg(tfm);
|
||||||
|
+ return container_of(alg, struct qce_alg_template, alg.skcipher);
|
||||||
|
}
|
||||||
|
|
||||||
|
-extern const struct qce_algo_ops ablkcipher_ops;
|
||||||
|
+extern const struct qce_algo_ops skcipher_ops;
|
||||||
|
|
||||||
|
#endif /* _CIPHER_H_ */
|
||||||
|
--- a/drivers/crypto/qce/common.c
|
||||||
|
+++ b/drivers/crypto/qce/common.c
|
||||||
|
@@ -304,13 +304,13 @@ go_proc:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int qce_setup_regs_ablkcipher(struct crypto_async_request *async_req,
|
||||||
|
+static int qce_setup_regs_skcipher(struct crypto_async_request *async_req,
|
||||||
|
u32 totallen, u32 offset)
|
||||||
|
{
|
||||||
|
- struct ablkcipher_request *req = ablkcipher_request_cast(async_req);
|
||||||
|
- struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req);
|
||||||
|
+ struct skcipher_request *req = skcipher_request_cast(async_req);
|
||||||
|
+ struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req);
|
||||||
|
struct qce_cipher_ctx *ctx = crypto_tfm_ctx(async_req->tfm);
|
||||||
|
- struct qce_alg_template *tmpl = to_cipher_tmpl(async_req->tfm);
|
||||||
|
+ struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req));
|
||||||
|
struct qce_device *qce = tmpl->qce;
|
||||||
|
__be32 enckey[QCE_MAX_CIPHER_KEY_SIZE / sizeof(__be32)] = {0};
|
||||||
|
__be32 enciv[QCE_MAX_IV_SIZE / sizeof(__be32)] = {0};
|
||||||
|
@@ -389,8 +389,8 @@ int qce_start(struct crypto_async_reques
|
||||||
|
u32 offset)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
- case CRYPTO_ALG_TYPE_ABLKCIPHER:
|
||||||
|
- return qce_setup_regs_ablkcipher(async_req, totallen, offset);
|
||||||
|
+ case CRYPTO_ALG_TYPE_SKCIPHER:
|
||||||
|
+ return qce_setup_regs_skcipher(async_req, totallen, offset);
|
||||||
|
case CRYPTO_ALG_TYPE_AHASH:
|
||||||
|
return qce_setup_regs_ahash(async_req, totallen, offset);
|
||||||
|
default:
|
||||||
|
--- a/drivers/crypto/qce/common.h
|
||||||
|
+++ b/drivers/crypto/qce/common.h
|
||||||
|
@@ -10,6 +10,7 @@
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <crypto/aes.h>
|
||||||
|
#include <crypto/hash.h>
|
||||||
|
+#include <crypto/internal/skcipher.h>
|
||||||
|
|
||||||
|
/* key size in bytes */
|
||||||
|
#define QCE_SHA_HMAC_KEY_SIZE 64
|
||||||
|
@@ -79,7 +80,7 @@ struct qce_alg_template {
|
||||||
|
unsigned long alg_flags;
|
||||||
|
const u32 *std_iv;
|
||||||
|
union {
|
||||||
|
- struct crypto_alg crypto;
|
||||||
|
+ struct skcipher_alg skcipher;
|
||||||
|
struct ahash_alg ahash;
|
||||||
|
} alg;
|
||||||
|
struct qce_device *qce;
|
||||||
|
--- a/drivers/crypto/qce/core.c
|
||||||
|
+++ b/drivers/crypto/qce/core.c
|
||||||
|
@@ -22,7 +22,7 @@
|
||||||
|
#define QCE_QUEUE_LENGTH 1
|
||||||
|
|
||||||
|
static const struct qce_algo_ops *qce_ops[] = {
|
||||||
|
- &ablkcipher_ops,
|
||||||
|
+ &skcipher_ops,
|
||||||
|
&ahash_ops,
|
||||||
|
};
|
||||||
|
|
||||||
|
--- a/drivers/crypto/qce/ablkcipher.c
|
||||||
|
+++ /dev/null
|
||||||
|
@@ -1,440 +0,0 @@
|
||||||
|
-// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
-/*
|
||||||
|
- * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
|
||||||
|
- */
|
||||||
|
-
|
||||||
|
-#include <linux/device.h>
|
||||||
|
-#include <linux/interrupt.h>
|
||||||
|
-#include <linux/types.h>
|
||||||
|
-#include <crypto/aes.h>
|
||||||
|
-#include <crypto/internal/des.h>
|
||||||
|
-#include <crypto/internal/skcipher.h>
|
||||||
|
-
|
||||||
|
-#include "cipher.h"
|
||||||
|
-
|
||||||
|
-static LIST_HEAD(ablkcipher_algs);
|
||||||
|
-
|
||||||
|
-static void qce_ablkcipher_done(void *data)
|
||||||
|
-{
|
||||||
|
- struct crypto_async_request *async_req = data;
|
||||||
|
- struct ablkcipher_request *req = ablkcipher_request_cast(async_req);
|
||||||
|
- struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req);
|
||||||
|
- struct qce_alg_template *tmpl = to_cipher_tmpl(async_req->tfm);
|
||||||
|
- struct qce_device *qce = tmpl->qce;
|
||||||
|
- enum dma_data_direction dir_src, dir_dst;
|
||||||
|
- u32 status;
|
||||||
|
- int error;
|
||||||
|
- bool diff_dst;
|
||||||
|
-
|
||||||
|
- diff_dst = (req->src != req->dst) ? true : false;
|
||||||
|
- dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL;
|
||||||
|
- dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL;
|
||||||
|
-
|
||||||
|
- error = qce_dma_terminate_all(&qce->dma);
|
||||||
|
- if (error)
|
||||||
|
- dev_dbg(qce->dev, "ablkcipher dma termination error (%d)\n",
|
||||||
|
- error);
|
||||||
|
-
|
||||||
|
- if (diff_dst)
|
||||||
|
- dma_unmap_sg(qce->dev, rctx->src_sg, rctx->src_nents, dir_src);
|
||||||
|
- dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst);
|
||||||
|
-
|
||||||
|
- sg_free_table(&rctx->dst_tbl);
|
||||||
|
-
|
||||||
|
- error = qce_check_status(qce, &status);
|
||||||
|
- if (error < 0)
|
||||||
|
- dev_dbg(qce->dev, "ablkcipher operation error (%x)\n", status);
|
||||||
|
-
|
||||||
|
- qce->async_req_done(tmpl->qce, error);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static int
|
||||||
|
-qce_ablkcipher_async_req_handle(struct crypto_async_request *async_req)
|
||||||
|
-{
|
||||||
|
- struct ablkcipher_request *req = ablkcipher_request_cast(async_req);
|
||||||
|
- struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req);
|
||||||
|
- struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
|
||||||
|
- struct qce_alg_template *tmpl = to_cipher_tmpl(async_req->tfm);
|
||||||
|
- struct qce_device *qce = tmpl->qce;
|
||||||
|
- enum dma_data_direction dir_src, dir_dst;
|
||||||
|
- struct scatterlist *sg;
|
||||||
|
- bool diff_dst;
|
||||||
|
- gfp_t gfp;
|
||||||
|
- int ret;
|
||||||
|
-
|
||||||
|
- rctx->iv = req->info;
|
||||||
|
- rctx->ivsize = crypto_ablkcipher_ivsize(ablkcipher);
|
||||||
|
- rctx->cryptlen = req->nbytes;
|
||||||
|
-
|
||||||
|
- diff_dst = (req->src != req->dst) ? true : false;
|
||||||
|
- dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL;
|
||||||
|
- dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL;
|
||||||
|
-
|
||||||
|
- rctx->src_nents = sg_nents_for_len(req->src, req->nbytes);
|
||||||
|
- if (diff_dst)
|
||||||
|
- rctx->dst_nents = sg_nents_for_len(req->dst, req->nbytes);
|
||||||
|
- else
|
||||||
|
- rctx->dst_nents = rctx->src_nents;
|
||||||
|
- if (rctx->src_nents < 0) {
|
||||||
|
- dev_err(qce->dev, "Invalid numbers of src SG.\n");
|
||||||
|
- return rctx->src_nents;
|
||||||
|
- }
|
||||||
|
- if (rctx->dst_nents < 0) {
|
||||||
|
- dev_err(qce->dev, "Invalid numbers of dst SG.\n");
|
||||||
|
- return -rctx->dst_nents;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- rctx->dst_nents += 1;
|
||||||
|
-
|
||||||
|
- gfp = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
|
||||||
|
- GFP_KERNEL : GFP_ATOMIC;
|
||||||
|
-
|
||||||
|
- ret = sg_alloc_table(&rctx->dst_tbl, rctx->dst_nents, gfp);
|
||||||
|
- if (ret)
|
||||||
|
- return ret;
|
||||||
|
-
|
||||||
|
- sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ);
|
||||||
|
-
|
||||||
|
- sg = qce_sgtable_add(&rctx->dst_tbl, req->dst);
|
||||||
|
- if (IS_ERR(sg)) {
|
||||||
|
- ret = PTR_ERR(sg);
|
||||||
|
- goto error_free;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg);
|
||||||
|
- if (IS_ERR(sg)) {
|
||||||
|
- ret = PTR_ERR(sg);
|
||||||
|
- goto error_free;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- sg_mark_end(sg);
|
||||||
|
- rctx->dst_sg = rctx->dst_tbl.sgl;
|
||||||
|
-
|
||||||
|
- ret = dma_map_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst);
|
||||||
|
- if (ret < 0)
|
||||||
|
- goto error_free;
|
||||||
|
-
|
||||||
|
- if (diff_dst) {
|
||||||
|
- ret = dma_map_sg(qce->dev, req->src, rctx->src_nents, dir_src);
|
||||||
|
- if (ret < 0)
|
||||||
|
- goto error_unmap_dst;
|
||||||
|
- rctx->src_sg = req->src;
|
||||||
|
- } else {
|
||||||
|
- rctx->src_sg = rctx->dst_sg;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, rctx->src_nents,
|
||||||
|
- rctx->dst_sg, rctx->dst_nents,
|
||||||
|
- qce_ablkcipher_done, async_req);
|
||||||
|
- if (ret)
|
||||||
|
- goto error_unmap_src;
|
||||||
|
-
|
||||||
|
- qce_dma_issue_pending(&qce->dma);
|
||||||
|
-
|
||||||
|
- ret = qce_start(async_req, tmpl->crypto_alg_type, req->nbytes, 0);
|
||||||
|
- if (ret)
|
||||||
|
- goto error_terminate;
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
-
|
||||||
|
-error_terminate:
|
||||||
|
- qce_dma_terminate_all(&qce->dma);
|
||||||
|
-error_unmap_src:
|
||||||
|
- if (diff_dst)
|
||||||
|
- dma_unmap_sg(qce->dev, req->src, rctx->src_nents, dir_src);
|
||||||
|
-error_unmap_dst:
|
||||||
|
- dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst);
|
||||||
|
-error_free:
|
||||||
|
- sg_free_table(&rctx->dst_tbl);
|
||||||
|
- return ret;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static int qce_ablkcipher_setkey(struct crypto_ablkcipher *ablk, const u8 *key,
|
||||||
|
- unsigned int keylen)
|
||||||
|
-{
|
||||||
|
- struct crypto_tfm *tfm = crypto_ablkcipher_tfm(ablk);
|
||||||
|
- struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||||
|
- int ret;
|
||||||
|
-
|
||||||
|
- if (!key || !keylen)
|
||||||
|
- return -EINVAL;
|
||||||
|
-
|
||||||
|
- switch (keylen) {
|
||||||
|
- case AES_KEYSIZE_128:
|
||||||
|
- case AES_KEYSIZE_256:
|
||||||
|
- break;
|
||||||
|
- default:
|
||||||
|
- goto fallback;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- ctx->enc_keylen = keylen;
|
||||||
|
- memcpy(ctx->enc_key, key, keylen);
|
||||||
|
- return 0;
|
||||||
|
-fallback:
|
||||||
|
- ret = crypto_sync_skcipher_setkey(ctx->fallback, key, keylen);
|
||||||
|
- if (!ret)
|
||||||
|
- ctx->enc_keylen = keylen;
|
||||||
|
- return ret;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static int qce_des_setkey(struct crypto_ablkcipher *ablk, const u8 *key,
|
||||||
|
- unsigned int keylen)
|
||||||
|
-{
|
||||||
|
- struct qce_cipher_ctx *ctx = crypto_ablkcipher_ctx(ablk);
|
||||||
|
- int err;
|
||||||
|
-
|
||||||
|
- err = verify_ablkcipher_des_key(ablk, key);
|
||||||
|
- if (err)
|
||||||
|
- return err;
|
||||||
|
-
|
||||||
|
- ctx->enc_keylen = keylen;
|
||||||
|
- memcpy(ctx->enc_key, key, keylen);
|
||||||
|
- return 0;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static int qce_des3_setkey(struct crypto_ablkcipher *ablk, const u8 *key,
|
||||||
|
- unsigned int keylen)
|
||||||
|
-{
|
||||||
|
- struct qce_cipher_ctx *ctx = crypto_ablkcipher_ctx(ablk);
|
||||||
|
- int err;
|
||||||
|
-
|
||||||
|
- err = verify_ablkcipher_des3_key(ablk, key);
|
||||||
|
- if (err)
|
||||||
|
- return err;
|
||||||
|
-
|
||||||
|
- ctx->enc_keylen = keylen;
|
||||||
|
- memcpy(ctx->enc_key, key, keylen);
|
||||||
|
- return 0;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static int qce_ablkcipher_crypt(struct ablkcipher_request *req, int encrypt)
|
||||||
|
-{
|
||||||
|
- struct crypto_tfm *tfm =
|
||||||
|
- crypto_ablkcipher_tfm(crypto_ablkcipher_reqtfm(req));
|
||||||
|
- struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||||
|
- struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req);
|
||||||
|
- struct qce_alg_template *tmpl = to_cipher_tmpl(tfm);
|
||||||
|
- int ret;
|
||||||
|
-
|
||||||
|
- rctx->flags = tmpl->alg_flags;
|
||||||
|
- rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT;
|
||||||
|
-
|
||||||
|
- if (IS_AES(rctx->flags) && ctx->enc_keylen != AES_KEYSIZE_128 &&
|
||||||
|
- ctx->enc_keylen != AES_KEYSIZE_256) {
|
||||||
|
- SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback);
|
||||||
|
-
|
||||||
|
- skcipher_request_set_sync_tfm(subreq, ctx->fallback);
|
||||||
|
- skcipher_request_set_callback(subreq, req->base.flags,
|
||||||
|
- NULL, NULL);
|
||||||
|
- skcipher_request_set_crypt(subreq, req->src, req->dst,
|
||||||
|
- req->nbytes, req->info);
|
||||||
|
- ret = encrypt ? crypto_skcipher_encrypt(subreq) :
|
||||||
|
- crypto_skcipher_decrypt(subreq);
|
||||||
|
- skcipher_request_zero(subreq);
|
||||||
|
- return ret;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- return tmpl->qce->async_req_enqueue(tmpl->qce, &req->base);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static int qce_ablkcipher_encrypt(struct ablkcipher_request *req)
|
||||||
|
-{
|
||||||
|
- return qce_ablkcipher_crypt(req, 1);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static int qce_ablkcipher_decrypt(struct ablkcipher_request *req)
|
||||||
|
-{
|
||||||
|
- return qce_ablkcipher_crypt(req, 0);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static int qce_ablkcipher_init(struct crypto_tfm *tfm)
|
||||||
|
-{
|
||||||
|
- struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||||
|
-
|
||||||
|
- memset(ctx, 0, sizeof(*ctx));
|
||||||
|
- tfm->crt_ablkcipher.reqsize = sizeof(struct qce_cipher_reqctx);
|
||||||
|
-
|
||||||
|
- ctx->fallback = crypto_alloc_sync_skcipher(crypto_tfm_alg_name(tfm),
|
||||||
|
- 0, CRYPTO_ALG_NEED_FALLBACK);
|
||||||
|
- return PTR_ERR_OR_ZERO(ctx->fallback);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static void qce_ablkcipher_exit(struct crypto_tfm *tfm)
|
||||||
|
-{
|
||||||
|
- struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||||
|
-
|
||||||
|
- crypto_free_sync_skcipher(ctx->fallback);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-struct qce_ablkcipher_def {
|
||||||
|
- unsigned long flags;
|
||||||
|
- const char *name;
|
||||||
|
- const char *drv_name;
|
||||||
|
- unsigned int blocksize;
|
||||||
|
- unsigned int ivsize;
|
||||||
|
- unsigned int min_keysize;
|
||||||
|
- unsigned int max_keysize;
|
||||||
|
-};
|
||||||
|
-
|
||||||
|
-static const struct qce_ablkcipher_def ablkcipher_def[] = {
|
||||||
|
- {
|
||||||
|
- .flags = QCE_ALG_AES | QCE_MODE_ECB,
|
||||||
|
- .name = "ecb(aes)",
|
||||||
|
- .drv_name = "ecb-aes-qce",
|
||||||
|
- .blocksize = AES_BLOCK_SIZE,
|
||||||
|
- .ivsize = AES_BLOCK_SIZE,
|
||||||
|
- .min_keysize = AES_MIN_KEY_SIZE,
|
||||||
|
- .max_keysize = AES_MAX_KEY_SIZE,
|
||||||
|
- },
|
||||||
|
- {
|
||||||
|
- .flags = QCE_ALG_AES | QCE_MODE_CBC,
|
||||||
|
- .name = "cbc(aes)",
|
||||||
|
- .drv_name = "cbc-aes-qce",
|
||||||
|
- .blocksize = AES_BLOCK_SIZE,
|
||||||
|
- .ivsize = AES_BLOCK_SIZE,
|
||||||
|
- .min_keysize = AES_MIN_KEY_SIZE,
|
||||||
|
- .max_keysize = AES_MAX_KEY_SIZE,
|
||||||
|
- },
|
||||||
|
- {
|
||||||
|
- .flags = QCE_ALG_AES | QCE_MODE_CTR,
|
||||||
|
- .name = "ctr(aes)",
|
||||||
|
- .drv_name = "ctr-aes-qce",
|
||||||
|
- .blocksize = AES_BLOCK_SIZE,
|
||||||
|
- .ivsize = AES_BLOCK_SIZE,
|
||||||
|
- .min_keysize = AES_MIN_KEY_SIZE,
|
||||||
|
- .max_keysize = AES_MAX_KEY_SIZE,
|
||||||
|
- },
|
||||||
|
- {
|
||||||
|
- .flags = QCE_ALG_AES | QCE_MODE_XTS,
|
||||||
|
- .name = "xts(aes)",
|
||||||
|
- .drv_name = "xts-aes-qce",
|
||||||
|
- .blocksize = AES_BLOCK_SIZE,
|
||||||
|
- .ivsize = AES_BLOCK_SIZE,
|
||||||
|
- .min_keysize = AES_MIN_KEY_SIZE,
|
||||||
|
- .max_keysize = AES_MAX_KEY_SIZE,
|
||||||
|
- },
|
||||||
|
- {
|
||||||
|
- .flags = QCE_ALG_DES | QCE_MODE_ECB,
|
||||||
|
- .name = "ecb(des)",
|
||||||
|
- .drv_name = "ecb-des-qce",
|
||||||
|
- .blocksize = DES_BLOCK_SIZE,
|
||||||
|
- .ivsize = 0,
|
||||||
|
- .min_keysize = DES_KEY_SIZE,
|
||||||
|
- .max_keysize = DES_KEY_SIZE,
|
||||||
|
- },
|
||||||
|
- {
|
||||||
|
- .flags = QCE_ALG_DES | QCE_MODE_CBC,
|
||||||
|
- .name = "cbc(des)",
|
||||||
|
- .drv_name = "cbc-des-qce",
|
||||||
|
- .blocksize = DES_BLOCK_SIZE,
|
||||||
|
- .ivsize = DES_BLOCK_SIZE,
|
||||||
|
- .min_keysize = DES_KEY_SIZE,
|
||||||
|
- .max_keysize = DES_KEY_SIZE,
|
||||||
|
- },
|
||||||
|
- {
|
||||||
|
- .flags = QCE_ALG_3DES | QCE_MODE_ECB,
|
||||||
|
- .name = "ecb(des3_ede)",
|
||||||
|
- .drv_name = "ecb-3des-qce",
|
||||||
|
- .blocksize = DES3_EDE_BLOCK_SIZE,
|
||||||
|
- .ivsize = 0,
|
||||||
|
- .min_keysize = DES3_EDE_KEY_SIZE,
|
||||||
|
- .max_keysize = DES3_EDE_KEY_SIZE,
|
||||||
|
- },
|
||||||
|
- {
|
||||||
|
- .flags = QCE_ALG_3DES | QCE_MODE_CBC,
|
||||||
|
- .name = "cbc(des3_ede)",
|
||||||
|
- .drv_name = "cbc-3des-qce",
|
||||||
|
- .blocksize = DES3_EDE_BLOCK_SIZE,
|
||||||
|
- .ivsize = DES3_EDE_BLOCK_SIZE,
|
||||||
|
- .min_keysize = DES3_EDE_KEY_SIZE,
|
||||||
|
- .max_keysize = DES3_EDE_KEY_SIZE,
|
||||||
|
- },
|
||||||
|
-};
|
||||||
|
-
|
||||||
|
-static int qce_ablkcipher_register_one(const struct qce_ablkcipher_def *def,
|
||||||
|
- struct qce_device *qce)
|
||||||
|
-{
|
||||||
|
- struct qce_alg_template *tmpl;
|
||||||
|
- struct crypto_alg *alg;
|
||||||
|
- int ret;
|
||||||
|
-
|
||||||
|
- tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL);
|
||||||
|
- if (!tmpl)
|
||||||
|
- return -ENOMEM;
|
||||||
|
-
|
||||||
|
- alg = &tmpl->alg.crypto;
|
||||||
|
-
|
||||||
|
- snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name);
|
||||||
|
- snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
|
||||||
|
- def->drv_name);
|
||||||
|
-
|
||||||
|
- alg->cra_blocksize = def->blocksize;
|
||||||
|
- alg->cra_ablkcipher.ivsize = def->ivsize;
|
||||||
|
- alg->cra_ablkcipher.min_keysize = def->min_keysize;
|
||||||
|
- alg->cra_ablkcipher.max_keysize = def->max_keysize;
|
||||||
|
- alg->cra_ablkcipher.setkey = IS_3DES(def->flags) ? qce_des3_setkey :
|
||||||
|
- IS_DES(def->flags) ? qce_des_setkey :
|
||||||
|
- qce_ablkcipher_setkey;
|
||||||
|
- alg->cra_ablkcipher.encrypt = qce_ablkcipher_encrypt;
|
||||||
|
- alg->cra_ablkcipher.decrypt = qce_ablkcipher_decrypt;
|
||||||
|
-
|
||||||
|
- alg->cra_priority = 300;
|
||||||
|
- alg->cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC |
|
||||||
|
- CRYPTO_ALG_NEED_FALLBACK | CRYPTO_ALG_KERN_DRIVER_ONLY;
|
||||||
|
- alg->cra_ctxsize = sizeof(struct qce_cipher_ctx);
|
||||||
|
- alg->cra_alignmask = 0;
|
||||||
|
- alg->cra_type = &crypto_ablkcipher_type;
|
||||||
|
- alg->cra_module = THIS_MODULE;
|
||||||
|
- alg->cra_init = qce_ablkcipher_init;
|
||||||
|
- alg->cra_exit = qce_ablkcipher_exit;
|
||||||
|
-
|
||||||
|
- INIT_LIST_HEAD(&tmpl->entry);
|
||||||
|
- tmpl->crypto_alg_type = CRYPTO_ALG_TYPE_ABLKCIPHER;
|
||||||
|
- tmpl->alg_flags = def->flags;
|
||||||
|
- tmpl->qce = qce;
|
||||||
|
-
|
||||||
|
- ret = crypto_register_alg(alg);
|
||||||
|
- if (ret) {
|
||||||
|
- kfree(tmpl);
|
||||||
|
- dev_err(qce->dev, "%s registration failed\n", alg->cra_name);
|
||||||
|
- return ret;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- list_add_tail(&tmpl->entry, &ablkcipher_algs);
|
||||||
|
- dev_dbg(qce->dev, "%s is registered\n", alg->cra_name);
|
||||||
|
- return 0;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static void qce_ablkcipher_unregister(struct qce_device *qce)
|
||||||
|
-{
|
||||||
|
- struct qce_alg_template *tmpl, *n;
|
||||||
|
-
|
||||||
|
- list_for_each_entry_safe(tmpl, n, &ablkcipher_algs, entry) {
|
||||||
|
- crypto_unregister_alg(&tmpl->alg.crypto);
|
||||||
|
- list_del(&tmpl->entry);
|
||||||
|
- kfree(tmpl);
|
||||||
|
- }
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static int qce_ablkcipher_register(struct qce_device *qce)
|
||||||
|
-{
|
||||||
|
- int ret, i;
|
||||||
|
-
|
||||||
|
- for (i = 0; i < ARRAY_SIZE(ablkcipher_def); i++) {
|
||||||
|
- ret = qce_ablkcipher_register_one(&ablkcipher_def[i], qce);
|
||||||
|
- if (ret)
|
||||||
|
- goto err;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
-err:
|
||||||
|
- qce_ablkcipher_unregister(qce);
|
||||||
|
- return ret;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-const struct qce_algo_ops ablkcipher_ops = {
|
||||||
|
- .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
|
||||||
|
- .register_algs = qce_ablkcipher_register,
|
||||||
|
- .unregister_algs = qce_ablkcipher_unregister,
|
||||||
|
- .async_req_handle = qce_ablkcipher_async_req_handle,
|
||||||
|
-};
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/drivers/crypto/qce/skcipher.c
|
||||||
|
@@ -0,0 +1,440 @@
|
||||||
|
+// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
+/*
|
||||||
|
+ * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include <linux/device.h>
|
||||||
|
+#include <linux/interrupt.h>
|
||||||
|
+#include <linux/types.h>
|
||||||
|
+#include <crypto/aes.h>
|
||||||
|
+#include <crypto/internal/des.h>
|
||||||
|
+#include <crypto/internal/skcipher.h>
|
||||||
|
+
|
||||||
|
+#include "cipher.h"
|
||||||
|
+
|
||||||
|
+static LIST_HEAD(skcipher_algs);
|
||||||
|
+
|
||||||
|
+static void qce_skcipher_done(void *data)
|
||||||
|
+{
|
||||||
|
+ struct crypto_async_request *async_req = data;
|
||||||
|
+ struct skcipher_request *req = skcipher_request_cast(async_req);
|
||||||
|
+ struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req);
|
||||||
|
+ struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req));
|
||||||
|
+ struct qce_device *qce = tmpl->qce;
|
||||||
|
+ enum dma_data_direction dir_src, dir_dst;
|
||||||
|
+ u32 status;
|
||||||
|
+ int error;
|
||||||
|
+ bool diff_dst;
|
||||||
|
+
|
||||||
|
+ diff_dst = (req->src != req->dst) ? true : false;
|
||||||
|
+ dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL;
|
||||||
|
+ dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL;
|
||||||
|
+
|
||||||
|
+ error = qce_dma_terminate_all(&qce->dma);
|
||||||
|
+ if (error)
|
||||||
|
+ dev_dbg(qce->dev, "skcipher dma termination error (%d)\n",
|
||||||
|
+ error);
|
||||||
|
+
|
||||||
|
+ if (diff_dst)
|
||||||
|
+ dma_unmap_sg(qce->dev, rctx->src_sg, rctx->src_nents, dir_src);
|
||||||
|
+ dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst);
|
||||||
|
+
|
||||||
|
+ sg_free_table(&rctx->dst_tbl);
|
||||||
|
+
|
||||||
|
+ error = qce_check_status(qce, &status);
|
||||||
|
+ if (error < 0)
|
||||||
|
+ dev_dbg(qce->dev, "skcipher operation error (%x)\n", status);
|
||||||
|
+
|
||||||
|
+ qce->async_req_done(tmpl->qce, error);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+qce_skcipher_async_req_handle(struct crypto_async_request *async_req)
|
||||||
|
+{
|
||||||
|
+ struct skcipher_request *req = skcipher_request_cast(async_req);
|
||||||
|
+ struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req);
|
||||||
|
+ struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req);
|
||||||
|
+ struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req));
|
||||||
|
+ struct qce_device *qce = tmpl->qce;
|
||||||
|
+ enum dma_data_direction dir_src, dir_dst;
|
||||||
|
+ struct scatterlist *sg;
|
||||||
|
+ bool diff_dst;
|
||||||
|
+ gfp_t gfp;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ rctx->iv = req->iv;
|
||||||
|
+ rctx->ivsize = crypto_skcipher_ivsize(skcipher);
|
||||||
|
+ rctx->cryptlen = req->cryptlen;
|
||||||
|
+
|
||||||
|
+ diff_dst = (req->src != req->dst) ? true : false;
|
||||||
|
+ dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL;
|
||||||
|
+ dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL;
|
||||||
|
+
|
||||||
|
+ rctx->src_nents = sg_nents_for_len(req->src, req->cryptlen);
|
||||||
|
+ if (diff_dst)
|
||||||
|
+ rctx->dst_nents = sg_nents_for_len(req->dst, req->cryptlen);
|
||||||
|
+ else
|
||||||
|
+ rctx->dst_nents = rctx->src_nents;
|
||||||
|
+ if (rctx->src_nents < 0) {
|
||||||
|
+ dev_err(qce->dev, "Invalid numbers of src SG.\n");
|
||||||
|
+ return rctx->src_nents;
|
||||||
|
+ }
|
||||||
|
+ if (rctx->dst_nents < 0) {
|
||||||
|
+ dev_err(qce->dev, "Invalid numbers of dst SG.\n");
|
||||||
|
+ return -rctx->dst_nents;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ rctx->dst_nents += 1;
|
||||||
|
+
|
||||||
|
+ gfp = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
|
||||||
|
+ GFP_KERNEL : GFP_ATOMIC;
|
||||||
|
+
|
||||||
|
+ ret = sg_alloc_table(&rctx->dst_tbl, rctx->dst_nents, gfp);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ);
|
||||||
|
+
|
||||||
|
+ sg = qce_sgtable_add(&rctx->dst_tbl, req->dst);
|
||||||
|
+ if (IS_ERR(sg)) {
|
||||||
|
+ ret = PTR_ERR(sg);
|
||||||
|
+ goto error_free;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg);
|
||||||
|
+ if (IS_ERR(sg)) {
|
||||||
|
+ ret = PTR_ERR(sg);
|
||||||
|
+ goto error_free;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ sg_mark_end(sg);
|
||||||
|
+ rctx->dst_sg = rctx->dst_tbl.sgl;
|
||||||
|
+
|
||||||
|
+ ret = dma_map_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst);
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ goto error_free;
|
||||||
|
+
|
||||||
|
+ if (diff_dst) {
|
||||||
|
+ ret = dma_map_sg(qce->dev, req->src, rctx->src_nents, dir_src);
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ goto error_unmap_dst;
|
||||||
|
+ rctx->src_sg = req->src;
|
||||||
|
+ } else {
|
||||||
|
+ rctx->src_sg = rctx->dst_sg;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, rctx->src_nents,
|
||||||
|
+ rctx->dst_sg, rctx->dst_nents,
|
||||||
|
+ qce_skcipher_done, async_req);
|
||||||
|
+ if (ret)
|
||||||
|
+ goto error_unmap_src;
|
||||||
|
+
|
||||||
|
+ qce_dma_issue_pending(&qce->dma);
|
||||||
|
+
|
||||||
|
+ ret = qce_start(async_req, tmpl->crypto_alg_type, req->cryptlen, 0);
|
||||||
|
+ if (ret)
|
||||||
|
+ goto error_terminate;
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+error_terminate:
|
||||||
|
+ qce_dma_terminate_all(&qce->dma);
|
||||||
|
+error_unmap_src:
|
||||||
|
+ if (diff_dst)
|
||||||
|
+ dma_unmap_sg(qce->dev, req->src, rctx->src_nents, dir_src);
|
||||||
|
+error_unmap_dst:
|
||||||
|
+ dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst);
|
||||||
|
+error_free:
|
||||||
|
+ sg_free_table(&rctx->dst_tbl);
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int qce_skcipher_setkey(struct crypto_skcipher *ablk, const u8 *key,
|
||||||
|
+ unsigned int keylen)
|
||||||
|
+{
|
||||||
|
+ struct crypto_tfm *tfm = crypto_skcipher_tfm(ablk);
|
||||||
|
+ struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ if (!key || !keylen)
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ switch (keylen) {
|
||||||
|
+ case AES_KEYSIZE_128:
|
||||||
|
+ case AES_KEYSIZE_256:
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ goto fallback;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ctx->enc_keylen = keylen;
|
||||||
|
+ memcpy(ctx->enc_key, key, keylen);
|
||||||
|
+ return 0;
|
||||||
|
+fallback:
|
||||||
|
+ ret = crypto_sync_skcipher_setkey(ctx->fallback, key, keylen);
|
||||||
|
+ if (!ret)
|
||||||
|
+ ctx->enc_keylen = keylen;
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int qce_des_setkey(struct crypto_skcipher *ablk, const u8 *key,
|
||||||
|
+ unsigned int keylen)
|
||||||
|
+{
|
||||||
|
+ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(ablk);
|
||||||
|
+ int err;
|
||||||
|
+
|
||||||
|
+ err = verify_skcipher_des_key(ablk, key);
|
||||||
|
+ if (err)
|
||||||
|
+ return err;
|
||||||
|
+
|
||||||
|
+ ctx->enc_keylen = keylen;
|
||||||
|
+ memcpy(ctx->enc_key, key, keylen);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int qce_des3_setkey(struct crypto_skcipher *ablk, const u8 *key,
|
||||||
|
+ unsigned int keylen)
|
||||||
|
+{
|
||||||
|
+ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(ablk);
|
||||||
|
+ int err;
|
||||||
|
+
|
||||||
|
+ err = verify_skcipher_des3_key(ablk, key);
|
||||||
|
+ if (err)
|
||||||
|
+ return err;
|
||||||
|
+
|
||||||
|
+ ctx->enc_keylen = keylen;
|
||||||
|
+ memcpy(ctx->enc_key, key, keylen);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt)
|
||||||
|
+{
|
||||||
|
+ struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
|
||||||
|
+ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm);
|
||||||
|
+ struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req);
|
||||||
|
+ struct qce_alg_template *tmpl = to_cipher_tmpl(tfm);
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ rctx->flags = tmpl->alg_flags;
|
||||||
|
+ rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT;
|
||||||
|
+
|
||||||
|
+ if (IS_AES(rctx->flags) && ctx->enc_keylen != AES_KEYSIZE_128 &&
|
||||||
|
+ ctx->enc_keylen != AES_KEYSIZE_256) {
|
||||||
|
+ SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback);
|
||||||
|
+
|
||||||
|
+ skcipher_request_set_sync_tfm(subreq, ctx->fallback);
|
||||||
|
+ skcipher_request_set_callback(subreq, req->base.flags,
|
||||||
|
+ NULL, NULL);
|
||||||
|
+ skcipher_request_set_crypt(subreq, req->src, req->dst,
|
||||||
|
+ req->cryptlen, req->iv);
|
||||||
|
+ ret = encrypt ? crypto_skcipher_encrypt(subreq) :
|
||||||
|
+ crypto_skcipher_decrypt(subreq);
|
||||||
|
+ skcipher_request_zero(subreq);
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return tmpl->qce->async_req_enqueue(tmpl->qce, &req->base);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int qce_skcipher_encrypt(struct skcipher_request *req)
|
||||||
|
+{
|
||||||
|
+ return qce_skcipher_crypt(req, 1);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int qce_skcipher_decrypt(struct skcipher_request *req)
|
||||||
|
+{
|
||||||
|
+ return qce_skcipher_crypt(req, 0);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int qce_skcipher_init(struct crypto_skcipher *tfm)
|
||||||
|
+{
|
||||||
|
+ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm);
|
||||||
|
+
|
||||||
|
+ memset(ctx, 0, sizeof(*ctx));
|
||||||
|
+ crypto_skcipher_set_reqsize(tfm, sizeof(struct qce_cipher_reqctx));
|
||||||
|
+
|
||||||
|
+ ctx->fallback = crypto_alloc_sync_skcipher(crypto_tfm_alg_name(&tfm->base),
|
||||||
|
+ 0, CRYPTO_ALG_NEED_FALLBACK);
|
||||||
|
+ return PTR_ERR_OR_ZERO(ctx->fallback);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void qce_skcipher_exit(struct crypto_skcipher *tfm)
|
||||||
|
+{
|
||||||
|
+ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm);
|
||||||
|
+
|
||||||
|
+ crypto_free_sync_skcipher(ctx->fallback);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+struct qce_skcipher_def {
|
||||||
|
+ unsigned long flags;
|
||||||
|
+ const char *name;
|
||||||
|
+ const char *drv_name;
|
||||||
|
+ unsigned int blocksize;
|
||||||
|
+ unsigned int ivsize;
|
||||||
|
+ unsigned int min_keysize;
|
||||||
|
+ unsigned int max_keysize;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static const struct qce_skcipher_def skcipher_def[] = {
|
||||||
|
+ {
|
||||||
|
+ .flags = QCE_ALG_AES | QCE_MODE_ECB,
|
||||||
|
+ .name = "ecb(aes)",
|
||||||
|
+ .drv_name = "ecb-aes-qce",
|
||||||
|
+ .blocksize = AES_BLOCK_SIZE,
|
||||||
|
+ .ivsize = AES_BLOCK_SIZE,
|
||||||
|
+ .min_keysize = AES_MIN_KEY_SIZE,
|
||||||
|
+ .max_keysize = AES_MAX_KEY_SIZE,
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ .flags = QCE_ALG_AES | QCE_MODE_CBC,
|
||||||
|
+ .name = "cbc(aes)",
|
||||||
|
+ .drv_name = "cbc-aes-qce",
|
||||||
|
+ .blocksize = AES_BLOCK_SIZE,
|
||||||
|
+ .ivsize = AES_BLOCK_SIZE,
|
||||||
|
+ .min_keysize = AES_MIN_KEY_SIZE,
|
||||||
|
+ .max_keysize = AES_MAX_KEY_SIZE,
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ .flags = QCE_ALG_AES | QCE_MODE_CTR,
|
||||||
|
+ .name = "ctr(aes)",
|
||||||
|
+ .drv_name = "ctr-aes-qce",
|
||||||
|
+ .blocksize = AES_BLOCK_SIZE,
|
||||||
|
+ .ivsize = AES_BLOCK_SIZE,
|
||||||
|
+ .min_keysize = AES_MIN_KEY_SIZE,
|
||||||
|
+ .max_keysize = AES_MAX_KEY_SIZE,
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ .flags = QCE_ALG_AES | QCE_MODE_XTS,
|
||||||
|
+ .name = "xts(aes)",
|
||||||
|
+ .drv_name = "xts-aes-qce",
|
||||||
|
+ .blocksize = AES_BLOCK_SIZE,
|
||||||
|
+ .ivsize = AES_BLOCK_SIZE,
|
||||||
|
+ .min_keysize = AES_MIN_KEY_SIZE,
|
||||||
|
+ .max_keysize = AES_MAX_KEY_SIZE,
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ .flags = QCE_ALG_DES | QCE_MODE_ECB,
|
||||||
|
+ .name = "ecb(des)",
|
||||||
|
+ .drv_name = "ecb-des-qce",
|
||||||
|
+ .blocksize = DES_BLOCK_SIZE,
|
||||||
|
+ .ivsize = 0,
|
||||||
|
+ .min_keysize = DES_KEY_SIZE,
|
||||||
|
+ .max_keysize = DES_KEY_SIZE,
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ .flags = QCE_ALG_DES | QCE_MODE_CBC,
|
||||||
|
+ .name = "cbc(des)",
|
||||||
|
+ .drv_name = "cbc-des-qce",
|
||||||
|
+ .blocksize = DES_BLOCK_SIZE,
|
||||||
|
+ .ivsize = DES_BLOCK_SIZE,
|
||||||
|
+ .min_keysize = DES_KEY_SIZE,
|
||||||
|
+ .max_keysize = DES_KEY_SIZE,
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ .flags = QCE_ALG_3DES | QCE_MODE_ECB,
|
||||||
|
+ .name = "ecb(des3_ede)",
|
||||||
|
+ .drv_name = "ecb-3des-qce",
|
||||||
|
+ .blocksize = DES3_EDE_BLOCK_SIZE,
|
||||||
|
+ .ivsize = 0,
|
||||||
|
+ .min_keysize = DES3_EDE_KEY_SIZE,
|
||||||
|
+ .max_keysize = DES3_EDE_KEY_SIZE,
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ .flags = QCE_ALG_3DES | QCE_MODE_CBC,
|
||||||
|
+ .name = "cbc(des3_ede)",
|
||||||
|
+ .drv_name = "cbc-3des-qce",
|
||||||
|
+ .blocksize = DES3_EDE_BLOCK_SIZE,
|
||||||
|
+ .ivsize = DES3_EDE_BLOCK_SIZE,
|
||||||
|
+ .min_keysize = DES3_EDE_KEY_SIZE,
|
||||||
|
+ .max_keysize = DES3_EDE_KEY_SIZE,
|
||||||
|
+ },
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int qce_skcipher_register_one(const struct qce_skcipher_def *def,
|
||||||
|
+ struct qce_device *qce)
|
||||||
|
+{
|
||||||
|
+ struct qce_alg_template *tmpl;
|
||||||
|
+ struct skcipher_alg *alg;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL);
|
||||||
|
+ if (!tmpl)
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+
|
||||||
|
+ alg = &tmpl->alg.skcipher;
|
||||||
|
+
|
||||||
|
+ snprintf(alg->base.cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name);
|
||||||
|
+ snprintf(alg->base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
|
||||||
|
+ def->drv_name);
|
||||||
|
+
|
||||||
|
+ alg->base.cra_blocksize = def->blocksize;
|
||||||
|
+ alg->ivsize = def->ivsize;
|
||||||
|
+ alg->min_keysize = def->min_keysize;
|
||||||
|
+ alg->max_keysize = def->max_keysize;
|
||||||
|
+ alg->setkey = IS_3DES(def->flags) ? qce_des3_setkey :
|
||||||
|
+ IS_DES(def->flags) ? qce_des_setkey :
|
||||||
|
+ qce_skcipher_setkey;
|
||||||
|
+ alg->encrypt = qce_skcipher_encrypt;
|
||||||
|
+ alg->decrypt = qce_skcipher_decrypt;
|
||||||
|
+
|
||||||
|
+ alg->base.cra_priority = 300;
|
||||||
|
+ alg->base.cra_flags = CRYPTO_ALG_ASYNC |
|
||||||
|
+ CRYPTO_ALG_NEED_FALLBACK |
|
||||||
|
+ CRYPTO_ALG_KERN_DRIVER_ONLY;
|
||||||
|
+ alg->base.cra_ctxsize = sizeof(struct qce_cipher_ctx);
|
||||||
|
+ alg->base.cra_alignmask = 0;
|
||||||
|
+ alg->base.cra_module = THIS_MODULE;
|
||||||
|
+
|
||||||
|
+ alg->init = qce_skcipher_init;
|
||||||
|
+ alg->exit = qce_skcipher_exit;
|
||||||
|
+
|
||||||
|
+ INIT_LIST_HEAD(&tmpl->entry);
|
||||||
|
+ tmpl->crypto_alg_type = CRYPTO_ALG_TYPE_SKCIPHER;
|
||||||
|
+ tmpl->alg_flags = def->flags;
|
||||||
|
+ tmpl->qce = qce;
|
||||||
|
+
|
||||||
|
+ ret = crypto_register_skcipher(alg);
|
||||||
|
+ if (ret) {
|
||||||
|
+ kfree(tmpl);
|
||||||
|
+ dev_err(qce->dev, "%s registration failed\n", alg->base.cra_name);
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ list_add_tail(&tmpl->entry, &skcipher_algs);
|
||||||
|
+ dev_dbg(qce->dev, "%s is registered\n", alg->base.cra_name);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void qce_skcipher_unregister(struct qce_device *qce)
|
||||||
|
+{
|
||||||
|
+ struct qce_alg_template *tmpl, *n;
|
||||||
|
+
|
||||||
|
+ list_for_each_entry_safe(tmpl, n, &skcipher_algs, entry) {
|
||||||
|
+ crypto_unregister_skcipher(&tmpl->alg.skcipher);
|
||||||
|
+ list_del(&tmpl->entry);
|
||||||
|
+ kfree(tmpl);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int qce_skcipher_register(struct qce_device *qce)
|
||||||
|
+{
|
||||||
|
+ int ret, i;
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < ARRAY_SIZE(skcipher_def); i++) {
|
||||||
|
+ ret = qce_skcipher_register_one(&skcipher_def[i], qce);
|
||||||
|
+ if (ret)
|
||||||
|
+ goto err;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+err:
|
||||||
|
+ qce_skcipher_unregister(qce);
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+const struct qce_algo_ops skcipher_ops = {
|
||||||
|
+ .type = CRYPTO_ALG_TYPE_SKCIPHER,
|
||||||
|
+ .register_algs = qce_skcipher_register,
|
||||||
|
+ .unregister_algs = qce_skcipher_unregister,
|
||||||
|
+ .async_req_handle = qce_skcipher_async_req_handle,
|
||||||
|
+};
|
|
@ -0,0 +1,43 @@
|
||||||
|
From bb5c863b3d3cbd10e80b2ebf409934a091058f54 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||||
|
Date: Fri, 20 Dec 2019 16:02:13 -0300
|
||||||
|
Subject: [PATCH 02/11] crypto: qce - fix ctr-aes-qce block, chunk sizes
|
||||||
|
|
||||||
|
Set blocksize of ctr-aes-qce to 1, so it can operate as a stream cipher,
|
||||||
|
adding the definition for chucksize instead, where the underlying block
|
||||||
|
size belongs.
|
||||||
|
|
||||||
|
Signed-off-by: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||||
|
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||||
|
---
|
||||||
|
drivers/crypto/qce/skcipher.c | 5 ++++-
|
||||||
|
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
--- a/drivers/crypto/qce/skcipher.c
|
||||||
|
+++ b/drivers/crypto/qce/skcipher.c
|
||||||
|
@@ -270,6 +270,7 @@ struct qce_skcipher_def {
|
||||||
|
const char *name;
|
||||||
|
const char *drv_name;
|
||||||
|
unsigned int blocksize;
|
||||||
|
+ unsigned int chunksize;
|
||||||
|
unsigned int ivsize;
|
||||||
|
unsigned int min_keysize;
|
||||||
|
unsigned int max_keysize;
|
||||||
|
@@ -298,7 +299,8 @@ static const struct qce_skcipher_def skc
|
||||||
|
.flags = QCE_ALG_AES | QCE_MODE_CTR,
|
||||||
|
.name = "ctr(aes)",
|
||||||
|
.drv_name = "ctr-aes-qce",
|
||||||
|
- .blocksize = AES_BLOCK_SIZE,
|
||||||
|
+ .blocksize = 1,
|
||||||
|
+ .chunksize = AES_BLOCK_SIZE,
|
||||||
|
.ivsize = AES_BLOCK_SIZE,
|
||||||
|
.min_keysize = AES_MIN_KEY_SIZE,
|
||||||
|
.max_keysize = AES_MAX_KEY_SIZE,
|
||||||
|
@@ -368,6 +370,7 @@ static int qce_skcipher_register_one(con
|
||||||
|
def->drv_name);
|
||||||
|
|
||||||
|
alg->base.cra_blocksize = def->blocksize;
|
||||||
|
+ alg->chunksize = def->chunksize;
|
||||||
|
alg->ivsize = def->ivsize;
|
||||||
|
alg->min_keysize = def->min_keysize;
|
||||||
|
alg->max_keysize = def->max_keysize;
|
|
@ -0,0 +1,60 @@
|
||||||
|
From 7de4c2bd196f111e39cc60f6197654aff23ba2b4 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||||
|
Date: Fri, 20 Dec 2019 16:02:14 -0300
|
||||||
|
Subject: [PATCH 03/11] crypto: qce - fix xts-aes-qce key sizes
|
||||||
|
|
||||||
|
XTS-mode uses two keys, so the keysizes should be doubled in
|
||||||
|
skcipher_def, and halved when checking if it is AES-128/192/256.
|
||||||
|
|
||||||
|
Signed-off-by: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||||
|
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||||
|
---
|
||||||
|
drivers/crypto/qce/skcipher.c | 13 ++++++++-----
|
||||||
|
1 file changed, 8 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
--- a/drivers/crypto/qce/skcipher.c
|
||||||
|
+++ b/drivers/crypto/qce/skcipher.c
|
||||||
|
@@ -154,12 +154,13 @@ static int qce_skcipher_setkey(struct cr
|
||||||
|
{
|
||||||
|
struct crypto_tfm *tfm = crypto_skcipher_tfm(ablk);
|
||||||
|
struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||||
|
+ unsigned long flags = to_cipher_tmpl(ablk)->alg_flags;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!key || !keylen)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
- switch (keylen) {
|
||||||
|
+ switch (IS_XTS(flags) ? keylen >> 1 : keylen) {
|
||||||
|
case AES_KEYSIZE_128:
|
||||||
|
case AES_KEYSIZE_256:
|
||||||
|
break;
|
||||||
|
@@ -213,13 +214,15 @@ static int qce_skcipher_crypt(struct skc
|
||||||
|
struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm);
|
||||||
|
struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req);
|
||||||
|
struct qce_alg_template *tmpl = to_cipher_tmpl(tfm);
|
||||||
|
+ int keylen;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
rctx->flags = tmpl->alg_flags;
|
||||||
|
rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT;
|
||||||
|
+ keylen = IS_XTS(rctx->flags) ? ctx->enc_keylen >> 1 : ctx->enc_keylen;
|
||||||
|
|
||||||
|
- if (IS_AES(rctx->flags) && ctx->enc_keylen != AES_KEYSIZE_128 &&
|
||||||
|
- ctx->enc_keylen != AES_KEYSIZE_256) {
|
||||||
|
+ if (IS_AES(rctx->flags) && keylen != AES_KEYSIZE_128 &&
|
||||||
|
+ keylen != AES_KEYSIZE_256) {
|
||||||
|
SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback);
|
||||||
|
|
||||||
|
skcipher_request_set_sync_tfm(subreq, ctx->fallback);
|
||||||
|
@@ -311,8 +314,8 @@ static const struct qce_skcipher_def skc
|
||||||
|
.drv_name = "xts-aes-qce",
|
||||||
|
.blocksize = AES_BLOCK_SIZE,
|
||||||
|
.ivsize = AES_BLOCK_SIZE,
|
||||||
|
- .min_keysize = AES_MIN_KEY_SIZE,
|
||||||
|
- .max_keysize = AES_MAX_KEY_SIZE,
|
||||||
|
+ .min_keysize = AES_MIN_KEY_SIZE * 2,
|
||||||
|
+ .max_keysize = AES_MAX_KEY_SIZE * 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.flags = QCE_ALG_DES | QCE_MODE_ECB,
|
|
@ -0,0 +1,85 @@
|
||||||
|
From 3ee50c896d712dc2fc8f34c2cd1918d035e74045 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||||
|
Date: Fri, 20 Dec 2019 16:02:15 -0300
|
||||||
|
Subject: [PATCH 04/11] crypto: qce - save a sg table slot for result buf
|
||||||
|
|
||||||
|
When ctr-aes-qce is used for gcm-mode, an extra sg entry for the
|
||||||
|
authentication tag is present, causing trouble when the qce driver
|
||||||
|
prepares the dst-results sg table for dma.
|
||||||
|
|
||||||
|
It computes the number of entries needed with sg_nents_for_len, leaving
|
||||||
|
out the tag entry. Then it creates a sg table with that number plus
|
||||||
|
one, used to store a result buffer.
|
||||||
|
|
||||||
|
When copying the sg table, there's no limit to the number of entries
|
||||||
|
copied, so the extra slot is filled with the authentication tag sg.
|
||||||
|
When the driver tries to add the result sg, the list is full, and it
|
||||||
|
returns EINVAL.
|
||||||
|
|
||||||
|
By limiting the number of sg entries copied to the dest table, the slot
|
||||||
|
for the result buffer is guaranteed to be unused.
|
||||||
|
|
||||||
|
Signed-off-by: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||||
|
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||||
|
---
|
||||||
|
drivers/crypto/qce/dma.c | 6 ++++--
|
||||||
|
drivers/crypto/qce/dma.h | 3 ++-
|
||||||
|
drivers/crypto/qce/skcipher.c | 4 ++--
|
||||||
|
3 files changed, 8 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
--- a/drivers/crypto/qce/dma.c
|
||||||
|
+++ b/drivers/crypto/qce/dma.c
|
||||||
|
@@ -47,7 +47,8 @@ void qce_dma_release(struct qce_dma_data
|
||||||
|
}
|
||||||
|
|
||||||
|
struct scatterlist *
|
||||||
|
-qce_sgtable_add(struct sg_table *sgt, struct scatterlist *new_sgl)
|
||||||
|
+qce_sgtable_add(struct sg_table *sgt, struct scatterlist *new_sgl,
|
||||||
|
+ int max_ents)
|
||||||
|
{
|
||||||
|
struct scatterlist *sg = sgt->sgl, *sg_last = NULL;
|
||||||
|
|
||||||
|
@@ -60,12 +61,13 @@ qce_sgtable_add(struct sg_table *sgt, st
|
||||||
|
if (!sg)
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
|
- while (new_sgl && sg) {
|
||||||
|
+ while (new_sgl && sg && max_ents) {
|
||||||
|
sg_set_page(sg, sg_page(new_sgl), new_sgl->length,
|
||||||
|
new_sgl->offset);
|
||||||
|
sg_last = sg;
|
||||||
|
sg = sg_next(sg);
|
||||||
|
new_sgl = sg_next(new_sgl);
|
||||||
|
+ max_ents--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sg_last;
|
||||||
|
--- a/drivers/crypto/qce/dma.h
|
||||||
|
+++ b/drivers/crypto/qce/dma.h
|
||||||
|
@@ -42,6 +42,7 @@ int qce_dma_prep_sgs(struct qce_dma_data
|
||||||
|
void qce_dma_issue_pending(struct qce_dma_data *dma);
|
||||||
|
int qce_dma_terminate_all(struct qce_dma_data *dma);
|
||||||
|
struct scatterlist *
|
||||||
|
-qce_sgtable_add(struct sg_table *sgt, struct scatterlist *sg_add);
|
||||||
|
+qce_sgtable_add(struct sg_table *sgt, struct scatterlist *sg_add,
|
||||||
|
+ int max_ents);
|
||||||
|
|
||||||
|
#endif /* _DMA_H_ */
|
||||||
|
--- a/drivers/crypto/qce/skcipher.c
|
||||||
|
+++ b/drivers/crypto/qce/skcipher.c
|
||||||
|
@@ -95,13 +95,13 @@ qce_skcipher_async_req_handle(struct cry
|
||||||
|
|
||||||
|
sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ);
|
||||||
|
|
||||||
|
- sg = qce_sgtable_add(&rctx->dst_tbl, req->dst);
|
||||||
|
+ sg = qce_sgtable_add(&rctx->dst_tbl, req->dst, rctx->dst_nents - 1);
|
||||||
|
if (IS_ERR(sg)) {
|
||||||
|
ret = PTR_ERR(sg);
|
||||||
|
goto error_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
- sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg);
|
||||||
|
+ sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg, 1);
|
||||||
|
if (IS_ERR(sg)) {
|
||||||
|
ret = PTR_ERR(sg);
|
||||||
|
goto error_free;
|
|
@ -0,0 +1,31 @@
|
||||||
|
From 3e806a12d10af2581aa26c37b58439286eab9782 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||||
|
Date: Fri, 20 Dec 2019 16:02:16 -0300
|
||||||
|
Subject: [PATCH 05/11] crypto: qce - update the skcipher IV
|
||||||
|
|
||||||
|
Update the IV after the completion of each cipher operation.
|
||||||
|
|
||||||
|
Signed-off-by: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||||
|
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||||
|
---
|
||||||
|
drivers/crypto/qce/skcipher.c | 2 ++
|
||||||
|
1 file changed, 2 insertions(+)
|
||||||
|
|
||||||
|
--- a/drivers/crypto/qce/skcipher.c
|
||||||
|
+++ b/drivers/crypto/qce/skcipher.c
|
||||||
|
@@ -21,6 +21,7 @@ static void qce_skcipher_done(void *data
|
||||||
|
struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req);
|
||||||
|
struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req));
|
||||||
|
struct qce_device *qce = tmpl->qce;
|
||||||
|
+ struct qce_result_dump *result_buf = qce->dma.result_buf;
|
||||||
|
enum dma_data_direction dir_src, dir_dst;
|
||||||
|
u32 status;
|
||||||
|
int error;
|
||||||
|
@@ -45,6 +46,7 @@ static void qce_skcipher_done(void *data
|
||||||
|
if (error < 0)
|
||||||
|
dev_dbg(qce->dev, "skcipher operation error (%x)\n", status);
|
||||||
|
|
||||||
|
+ memcpy(rctx->iv, result_buf->encr_cntr_iv, rctx->ivsize);
|
||||||
|
qce->async_req_done(tmpl->qce, error);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
From 8ceda883205db6dfedb82e39f67feae3b50c95a1 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||||
|
Date: Fri, 20 Dec 2019 16:02:17 -0300
|
||||||
|
Subject: [PATCH 06/11] crypto: qce - initialize fallback only for AES
|
||||||
|
|
||||||
|
Adjust cra_flags to add CRYPTO_NEED_FALLBACK only for AES ciphers, where
|
||||||
|
AES-192 is not handled by the qce hardware, and don't allocate & free
|
||||||
|
the fallback skcipher for other algorithms.
|
||||||
|
|
||||||
|
Signed-off-by: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||||
|
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||||
|
---
|
||||||
|
drivers/crypto/qce/skcipher.c | 17 ++++++++++++++---
|
||||||
|
1 file changed, 14 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
--- a/drivers/crypto/qce/skcipher.c
|
||||||
|
+++ b/drivers/crypto/qce/skcipher.c
|
||||||
|
@@ -257,7 +257,14 @@ static int qce_skcipher_init(struct cryp
|
||||||
|
|
||||||
|
memset(ctx, 0, sizeof(*ctx));
|
||||||
|
crypto_skcipher_set_reqsize(tfm, sizeof(struct qce_cipher_reqctx));
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int qce_skcipher_init_fallback(struct crypto_skcipher *tfm)
|
||||||
|
+{
|
||||||
|
+ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm);
|
||||||
|
|
||||||
|
+ qce_skcipher_init(tfm);
|
||||||
|
ctx->fallback = crypto_alloc_sync_skcipher(crypto_tfm_alg_name(&tfm->base),
|
||||||
|
0, CRYPTO_ALG_NEED_FALLBACK);
|
||||||
|
return PTR_ERR_OR_ZERO(ctx->fallback);
|
||||||
|
@@ -387,14 +394,18 @@ static int qce_skcipher_register_one(con
|
||||||
|
|
||||||
|
alg->base.cra_priority = 300;
|
||||||
|
alg->base.cra_flags = CRYPTO_ALG_ASYNC |
|
||||||
|
- CRYPTO_ALG_NEED_FALLBACK |
|
||||||
|
CRYPTO_ALG_KERN_DRIVER_ONLY;
|
||||||
|
alg->base.cra_ctxsize = sizeof(struct qce_cipher_ctx);
|
||||||
|
alg->base.cra_alignmask = 0;
|
||||||
|
alg->base.cra_module = THIS_MODULE;
|
||||||
|
|
||||||
|
- alg->init = qce_skcipher_init;
|
||||||
|
- alg->exit = qce_skcipher_exit;
|
||||||
|
+ if (IS_AES(def->flags)) {
|
||||||
|
+ alg->base.cra_flags |= CRYPTO_ALG_NEED_FALLBACK;
|
||||||
|
+ alg->init = qce_skcipher_init_fallback;
|
||||||
|
+ alg->exit = qce_skcipher_exit;
|
||||||
|
+ } else {
|
||||||
|
+ alg->init = qce_skcipher_init;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
INIT_LIST_HEAD(&tmpl->entry);
|
||||||
|
tmpl->crypto_alg_type = CRYPTO_ALG_TYPE_SKCIPHER;
|
|
@ -0,0 +1,89 @@
|
||||||
|
From d6364b8128439a8c0e381f80c38667de9f15eef8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||||
|
Date: Fri, 7 Feb 2020 12:02:25 -0300
|
||||||
|
Subject: [PATCH 09/11] crypto: qce - use cryptlen when adding extra sgl
|
||||||
|
|
||||||
|
The qce crypto driver appends an extra entry to the dst sgl, to maintain
|
||||||
|
private state information.
|
||||||
|
|
||||||
|
When the gcm driver sends requests to the ctr skcipher, it passes the
|
||||||
|
authentication tag after the actual crypto payload, but it must not be
|
||||||
|
touched.
|
||||||
|
|
||||||
|
Commit 1336c2221bee ("crypto: qce - save a sg table slot for result
|
||||||
|
buf") limited the destination sgl to avoid overwriting the
|
||||||
|
authentication tag but it assumed the tag would be in a separate sgl
|
||||||
|
entry.
|
||||||
|
|
||||||
|
This is not always the case, so it is better to limit the length of the
|
||||||
|
destination buffer to req->cryptlen before appending the result buf.
|
||||||
|
|
||||||
|
Signed-off-by: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||||
|
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||||
|
---
|
||||||
|
drivers/crypto/qce/dma.c | 11 ++++++-----
|
||||||
|
drivers/crypto/qce/dma.h | 2 +-
|
||||||
|
drivers/crypto/qce/skcipher.c | 5 +++--
|
||||||
|
3 files changed, 10 insertions(+), 8 deletions(-)
|
||||||
|
|
||||||
|
--- a/drivers/crypto/qce/dma.c
|
||||||
|
+++ b/drivers/crypto/qce/dma.c
|
||||||
|
@@ -48,9 +48,10 @@ void qce_dma_release(struct qce_dma_data
|
||||||
|
|
||||||
|
struct scatterlist *
|
||||||
|
qce_sgtable_add(struct sg_table *sgt, struct scatterlist *new_sgl,
|
||||||
|
- int max_ents)
|
||||||
|
+ unsigned int max_len)
|
||||||
|
{
|
||||||
|
struct scatterlist *sg = sgt->sgl, *sg_last = NULL;
|
||||||
|
+ unsigned int new_len;
|
||||||
|
|
||||||
|
while (sg) {
|
||||||
|
if (!sg_page(sg))
|
||||||
|
@@ -61,13 +62,13 @@ qce_sgtable_add(struct sg_table *sgt, st
|
||||||
|
if (!sg)
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
|
- while (new_sgl && sg && max_ents) {
|
||||||
|
- sg_set_page(sg, sg_page(new_sgl), new_sgl->length,
|
||||||
|
- new_sgl->offset);
|
||||||
|
+ while (new_sgl && sg && max_len) {
|
||||||
|
+ new_len = new_sgl->length > max_len ? max_len : new_sgl->length;
|
||||||
|
+ sg_set_page(sg, sg_page(new_sgl), new_len, new_sgl->offset);
|
||||||
|
sg_last = sg;
|
||||||
|
sg = sg_next(sg);
|
||||||
|
new_sgl = sg_next(new_sgl);
|
||||||
|
- max_ents--;
|
||||||
|
+ max_len -= new_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sg_last;
|
||||||
|
--- a/drivers/crypto/qce/dma.h
|
||||||
|
+++ b/drivers/crypto/qce/dma.h
|
||||||
|
@@ -43,6 +43,6 @@ void qce_dma_issue_pending(struct qce_dm
|
||||||
|
int qce_dma_terminate_all(struct qce_dma_data *dma);
|
||||||
|
struct scatterlist *
|
||||||
|
qce_sgtable_add(struct sg_table *sgt, struct scatterlist *sg_add,
|
||||||
|
- int max_ents);
|
||||||
|
+ unsigned int max_len);
|
||||||
|
|
||||||
|
#endif /* _DMA_H_ */
|
||||||
|
--- a/drivers/crypto/qce/skcipher.c
|
||||||
|
+++ b/drivers/crypto/qce/skcipher.c
|
||||||
|
@@ -97,13 +97,14 @@ qce_skcipher_async_req_handle(struct cry
|
||||||
|
|
||||||
|
sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ);
|
||||||
|
|
||||||
|
- sg = qce_sgtable_add(&rctx->dst_tbl, req->dst, rctx->dst_nents - 1);
|
||||||
|
+ sg = qce_sgtable_add(&rctx->dst_tbl, req->dst, req->cryptlen);
|
||||||
|
if (IS_ERR(sg)) {
|
||||||
|
ret = PTR_ERR(sg);
|
||||||
|
goto error_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
- sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg, 1);
|
||||||
|
+ sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg,
|
||||||
|
+ QCE_RESULT_BUF_SZ);
|
||||||
|
if (IS_ERR(sg)) {
|
||||||
|
ret = PTR_ERR(sg);
|
||||||
|
goto error_free;
|
|
@ -0,0 +1,113 @@
|
||||||
|
From ce163ba0bf298f1707321ac025ef639f88e62801 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||||
|
Date: Fri, 7 Feb 2020 12:02:26 -0300
|
||||||
|
Subject: [PATCH 10/11] crypto: qce - use AES fallback for small requests
|
||||||
|
|
||||||
|
Process small blocks using the fallback cipher, as a workaround for an
|
||||||
|
observed failure (DMA-related, apparently) when computing the GCM ghash
|
||||||
|
key. This brings a speed gain as well, since it avoids the latency of
|
||||||
|
using the hardware engine to process small blocks.
|
||||||
|
|
||||||
|
Using software for all 16-byte requests would be enough to make GCM
|
||||||
|
work, but to increase performance, a larger threshold would be better.
|
||||||
|
Measuring the performance of supported ciphers with openssl speed,
|
||||||
|
software matches hardware at around 768-1024 bytes.
|
||||||
|
|
||||||
|
Considering the 256-bit ciphers, software is 2-3 times faster than qce
|
||||||
|
at 256-bytes, 30% faster at 512, and about even at 768-bytes. With
|
||||||
|
128-bit keys, the break-even point would be around 1024-bytes.
|
||||||
|
|
||||||
|
This adds the 'aes_sw_max_len' parameter, to set the largest request
|
||||||
|
length processed by the software fallback. Its default is being set to
|
||||||
|
512 bytes, a little lower than the break-even point, to balance the cost
|
||||||
|
in CPU usage.
|
||||||
|
|
||||||
|
Signed-off-by: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||||
|
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- a/drivers/crypto/Kconfig
|
||||||
|
+++ b/drivers/crypto/Kconfig
|
||||||
|
@@ -628,6 +628,29 @@ config CRYPTO_DEV_QCE
|
||||||
|
hardware. To compile this driver as a module, choose M here. The
|
||||||
|
module will be called qcrypto.
|
||||||
|
|
||||||
|
+config CRYPTO_DEV_QCE_SW_MAX_LEN
|
||||||
|
+ int "Default maximum request size to use software for AES"
|
||||||
|
+ depends on CRYPTO_DEV_QCE && CRYPTO_DEV_QCE_SKCIPHER
|
||||||
|
+ default 512
|
||||||
|
+ help
|
||||||
|
+ This sets the default maximum request size to perform AES requests
|
||||||
|
+ using software instead of the crypto engine. It can be changed by
|
||||||
|
+ setting the aes_sw_max_len parameter.
|
||||||
|
+
|
||||||
|
+ Small blocks are processed faster in software than hardware.
|
||||||
|
+ Considering the 256-bit ciphers, software is 2-3 times faster than
|
||||||
|
+ qce at 256-bytes, 30% faster at 512, and about even at 768-bytes.
|
||||||
|
+ With 128-bit keys, the break-even point would be around 1024-bytes.
|
||||||
|
+
|
||||||
|
+ The default is set a little lower, to 512 bytes, to balance the
|
||||||
|
+ cost in CPU usage. The minimum recommended setting is 16-bytes
|
||||||
|
+ (1 AES block), since AES-GCM will fail if you set it lower.
|
||||||
|
+ Setting this to zero will send all requests to the hardware.
|
||||||
|
+
|
||||||
|
+ Note that 192-bit keys are not supported by the hardware and are
|
||||||
|
+ always processed by the software fallback, and all DES requests
|
||||||
|
+ are done by the hardware.
|
||||||
|
+
|
||||||
|
config CRYPTO_DEV_QCOM_RNG
|
||||||
|
tristate "Qualcomm Random Number Generator Driver"
|
||||||
|
depends on ARCH_QCOM || COMPILE_TEST
|
||||||
|
--- a/drivers/crypto/qce/skcipher.c
|
||||||
|
+++ b/drivers/crypto/qce/skcipher.c
|
||||||
|
@@ -5,6 +5,7 @@
|
||||||
|
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
+#include <linux/moduleparam.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <crypto/aes.h>
|
||||||
|
#include <crypto/internal/des.h>
|
||||||
|
@@ -12,6 +13,13 @@
|
||||||
|
|
||||||
|
#include "cipher.h"
|
||||||
|
|
||||||
|
+static unsigned int aes_sw_max_len = CONFIG_CRYPTO_DEV_QCE_SW_MAX_LEN;
|
||||||
|
+module_param(aes_sw_max_len, uint, 0644);
|
||||||
|
+MODULE_PARM_DESC(aes_sw_max_len,
|
||||||
|
+ "Only use hardware for AES requests larger than this "
|
||||||
|
+ "[0=always use hardware; anything <16 breaks AES-GCM; default="
|
||||||
|
+ __stringify(CONFIG_CRYPTO_DEV_QCE_SOFT_THRESHOLD)"]");
|
||||||
|
+
|
||||||
|
static LIST_HEAD(skcipher_algs);
|
||||||
|
|
||||||
|
static void qce_skcipher_done(void *data)
|
||||||
|
@@ -166,15 +174,10 @@ static int qce_skcipher_setkey(struct cr
|
||||||
|
switch (IS_XTS(flags) ? keylen >> 1 : keylen) {
|
||||||
|
case AES_KEYSIZE_128:
|
||||||
|
case AES_KEYSIZE_256:
|
||||||
|
+ memcpy(ctx->enc_key, key, keylen);
|
||||||
|
break;
|
||||||
|
- default:
|
||||||
|
- goto fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
- ctx->enc_keylen = keylen;
|
||||||
|
- memcpy(ctx->enc_key, key, keylen);
|
||||||
|
- return 0;
|
||||||
|
-fallback:
|
||||||
|
ret = crypto_sync_skcipher_setkey(ctx->fallback, key, keylen);
|
||||||
|
if (!ret)
|
||||||
|
ctx->enc_keylen = keylen;
|
||||||
|
@@ -224,8 +227,9 @@ static int qce_skcipher_crypt(struct skc
|
||||||
|
rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT;
|
||||||
|
keylen = IS_XTS(rctx->flags) ? ctx->enc_keylen >> 1 : ctx->enc_keylen;
|
||||||
|
|
||||||
|
- if (IS_AES(rctx->flags) && keylen != AES_KEYSIZE_128 &&
|
||||||
|
- keylen != AES_KEYSIZE_256) {
|
||||||
|
+ if (IS_AES(rctx->flags) &&
|
||||||
|
+ ((keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) ||
|
||||||
|
+ req->cryptlen <= aes_sw_max_len)) {
|
||||||
|
SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback);
|
||||||
|
|
||||||
|
skcipher_request_set_sync_tfm(subreq, ctx->fallback);
|
|
@ -0,0 +1,59 @@
|
||||||
|
From 7f19380b2cfd412dcef2facefb3f6c62788864d7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||||
|
Date: Fri, 7 Feb 2020 12:02:27 -0300
|
||||||
|
Subject: [PATCH 11/11] crypto: qce - handle AES-XTS cases that qce fails
|
||||||
|
|
||||||
|
QCE hangs when presented with an AES-XTS request whose length is larger
|
||||||
|
than QCE_SECTOR_SIZE (512-bytes), and is not a multiple of it. Let the
|
||||||
|
fallback cipher handle them.
|
||||||
|
|
||||||
|
Signed-off-by: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||||
|
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||||
|
---
|
||||||
|
drivers/crypto/qce/common.c | 2 --
|
||||||
|
drivers/crypto/qce/common.h | 3 +++
|
||||||
|
drivers/crypto/qce/skcipher.c | 9 +++++++--
|
||||||
|
3 files changed, 10 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
--- a/drivers/crypto/qce/common.c
|
||||||
|
+++ b/drivers/crypto/qce/common.c
|
||||||
|
@@ -15,8 +15,6 @@
|
||||||
|
#include "regs-v5.h"
|
||||||
|
#include "sha.h"
|
||||||
|
|
||||||
|
-#define QCE_SECTOR_SIZE 512
|
||||||
|
-
|
||||||
|
static inline u32 qce_read(struct qce_device *qce, u32 offset)
|
||||||
|
{
|
||||||
|
return readl(qce->base + offset);
|
||||||
|
--- a/drivers/crypto/qce/common.h
|
||||||
|
+++ b/drivers/crypto/qce/common.h
|
||||||
|
@@ -12,6 +12,9 @@
|
||||||
|
#include <crypto/hash.h>
|
||||||
|
#include <crypto/internal/skcipher.h>
|
||||||
|
|
||||||
|
+/* xts du size */
|
||||||
|
+#define QCE_SECTOR_SIZE 512
|
||||||
|
+
|
||||||
|
/* key size in bytes */
|
||||||
|
#define QCE_SHA_HMAC_KEY_SIZE 64
|
||||||
|
#define QCE_MAX_CIPHER_KEY_SIZE AES_KEYSIZE_256
|
||||||
|
--- a/drivers/crypto/qce/skcipher.c
|
||||||
|
+++ b/drivers/crypto/qce/skcipher.c
|
||||||
|
@@ -227,9 +227,14 @@ static int qce_skcipher_crypt(struct skc
|
||||||
|
rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT;
|
||||||
|
keylen = IS_XTS(rctx->flags) ? ctx->enc_keylen >> 1 : ctx->enc_keylen;
|
||||||
|
|
||||||
|
+ /* qce is hanging when AES-XTS request len > QCE_SECTOR_SIZE and
|
||||||
|
+ * is not a multiple of it; pass such requests to the fallback
|
||||||
|
+ */
|
||||||
|
if (IS_AES(rctx->flags) &&
|
||||||
|
- ((keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) ||
|
||||||
|
- req->cryptlen <= aes_sw_max_len)) {
|
||||||
|
+ (((keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) ||
|
||||||
|
+ req->cryptlen <= aes_sw_max_len) ||
|
||||||
|
+ (IS_XTS(rctx->flags) && req->cryptlen > QCE_SECTOR_SIZE &&
|
||||||
|
+ req->cryptlen % QCE_SECTOR_SIZE))) {
|
||||||
|
SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback);
|
||||||
|
|
||||||
|
skcipher_request_set_sync_tfm(subreq, ctx->fallback);
|
|
@ -0,0 +1,419 @@
|
||||||
|
From 59e056cda4beb5412e3653e6360c2eb0fa770baa Mon Sep 17 00:00:00 2001
|
||||||
|
From: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||||
|
Date: Fri, 20 Dec 2019 16:02:18 -0300
|
||||||
|
Subject: [PATCH 07/11] crypto: qce - allow building only hashes/ciphers
|
||||||
|
|
||||||
|
Allow the user to choose whether to build support for all algorithms
|
||||||
|
(default), hashes-only, or skciphers-only.
|
||||||
|
|
||||||
|
The QCE engine does not appear to scale as well as the CPU to handle
|
||||||
|
multiple crypto requests. While the ipq40xx chips have 4-core CPUs, the
|
||||||
|
QCE handles only 2 requests in parallel.
|
||||||
|
|
||||||
|
Ipsec throughput seems to improve when disabling either family of
|
||||||
|
algorithms, sharing the load with the CPU. Enabling skciphers-only
|
||||||
|
appears to work best.
|
||||||
|
|
||||||
|
Signed-off-by: Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||||
|
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- a/drivers/crypto/Kconfig
|
||||||
|
+++ b/drivers/crypto/Kconfig
|
||||||
|
@@ -616,6 +616,14 @@ config CRYPTO_DEV_QCE
|
||||||
|
tristate "Qualcomm crypto engine accelerator"
|
||||||
|
depends on ARCH_QCOM || COMPILE_TEST
|
||||||
|
depends on HAS_IOMEM
|
||||||
|
+ help
|
||||||
|
+ This driver supports Qualcomm crypto engine accelerator
|
||||||
|
+ hardware. To compile this driver as a module, choose M here. The
|
||||||
|
+ module will be called qcrypto.
|
||||||
|
+
|
||||||
|
+config CRYPTO_DEV_QCE_SKCIPHER
|
||||||
|
+ bool
|
||||||
|
+ depends on CRYPTO_DEV_QCE
|
||||||
|
select CRYPTO_AES
|
||||||
|
select CRYPTO_LIB_DES
|
||||||
|
select CRYPTO_ECB
|
||||||
|
@@ -623,10 +631,57 @@ config CRYPTO_DEV_QCE
|
||||||
|
select CRYPTO_XTS
|
||||||
|
select CRYPTO_CTR
|
||||||
|
select CRYPTO_BLKCIPHER
|
||||||
|
+
|
||||||
|
+config CRYPTO_DEV_QCE_SHA
|
||||||
|
+ bool
|
||||||
|
+ depends on CRYPTO_DEV_QCE
|
||||||
|
+
|
||||||
|
+choice
|
||||||
|
+ prompt "Algorithms enabled for QCE acceleration"
|
||||||
|
+ default CRYPTO_DEV_QCE_ENABLE_ALL
|
||||||
|
+ depends on CRYPTO_DEV_QCE
|
||||||
|
help
|
||||||
|
- This driver supports Qualcomm crypto engine accelerator
|
||||||
|
- hardware. To compile this driver as a module, choose M here. The
|
||||||
|
- module will be called qcrypto.
|
||||||
|
+ This option allows to choose whether to build support for all algorihtms
|
||||||
|
+ (default), hashes-only, or skciphers-only.
|
||||||
|
+
|
||||||
|
+ The QCE engine does not appear to scale as well as the CPU to handle
|
||||||
|
+ multiple crypto requests. While the ipq40xx chips have 4-core CPUs, the
|
||||||
|
+ QCE handles only 2 requests in parallel.
|
||||||
|
+
|
||||||
|
+ Ipsec throughput seems to improve when disabling either family of
|
||||||
|
+ algorithms, sharing the load with the CPU. Enabling skciphers-only
|
||||||
|
+ appears to work best.
|
||||||
|
+
|
||||||
|
+ config CRYPTO_DEV_QCE_ENABLE_ALL
|
||||||
|
+ bool "All supported algorithms"
|
||||||
|
+ select CRYPTO_DEV_QCE_SKCIPHER
|
||||||
|
+ select CRYPTO_DEV_QCE_SHA
|
||||||
|
+ help
|
||||||
|
+ Enable all supported algorithms:
|
||||||
|
+ - AES (CBC, CTR, ECB, XTS)
|
||||||
|
+ - 3DES (CBC, ECB)
|
||||||
|
+ - DES (CBC, ECB)
|
||||||
|
+ - SHA1, HMAC-SHA1
|
||||||
|
+ - SHA256, HMAC-SHA256
|
||||||
|
+
|
||||||
|
+ config CRYPTO_DEV_QCE_ENABLE_SKCIPHER
|
||||||
|
+ bool "Symmetric-key ciphers only"
|
||||||
|
+ select CRYPTO_DEV_QCE_SKCIPHER
|
||||||
|
+ help
|
||||||
|
+ Enable symmetric-key ciphers only:
|
||||||
|
+ - AES (CBC, CTR, ECB, XTS)
|
||||||
|
+ - 3DES (ECB, CBC)
|
||||||
|
+ - DES (ECB, CBC)
|
||||||
|
+
|
||||||
|
+ config CRYPTO_DEV_QCE_ENABLE_SHA
|
||||||
|
+ bool "Hash/HMAC only"
|
||||||
|
+ select CRYPTO_DEV_QCE_SHA
|
||||||
|
+ help
|
||||||
|
+ Enable hashes/HMAC algorithms only:
|
||||||
|
+ - SHA1, HMAC-SHA1
|
||||||
|
+ - SHA256, HMAC-SHA256
|
||||||
|
+
|
||||||
|
+endchoice
|
||||||
|
|
||||||
|
config CRYPTO_DEV_QCE_SW_MAX_LEN
|
||||||
|
int "Default maximum request size to use software for AES"
|
||||||
|
--- a/drivers/crypto/qce/Makefile
|
||||||
|
+++ b/drivers/crypto/qce/Makefile
|
||||||
|
@@ -2,6 +2,7 @@
|
||||||
|
obj-$(CONFIG_CRYPTO_DEV_QCE) += qcrypto.o
|
||||||
|
qcrypto-objs := core.o \
|
||||||
|
common.o \
|
||||||
|
- dma.o \
|
||||||
|
- sha.o \
|
||||||
|
- skcipher.o
|
||||||
|
+ dma.o
|
||||||
|
+
|
||||||
|
+qcrypto-$(CONFIG_CRYPTO_DEV_QCE_SHA) += sha.o
|
||||||
|
+qcrypto-$(CONFIG_CRYPTO_DEV_QCE_SKCIPHER) += skcipher.o
|
||||||
|
--- a/drivers/crypto/qce/common.c
|
||||||
|
+++ b/drivers/crypto/qce/common.c
|
||||||
|
@@ -43,52 +43,56 @@ qce_clear_array(struct qce_device *qce,
|
||||||
|
qce_write(qce, offset + i * sizeof(u32), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static u32 qce_encr_cfg(unsigned long flags, u32 aes_key_size)
|
||||||
|
+static u32 qce_config_reg(struct qce_device *qce, int little)
|
||||||
|
{
|
||||||
|
- u32 cfg = 0;
|
||||||
|
+ u32 beats = (qce->burst_size >> 3) - 1;
|
||||||
|
+ u32 pipe_pair = qce->pipe_pair_id;
|
||||||
|
+ u32 config;
|
||||||
|
|
||||||
|
- if (IS_AES(flags)) {
|
||||||
|
- if (aes_key_size == AES_KEYSIZE_128)
|
||||||
|
- cfg |= ENCR_KEY_SZ_AES128 << ENCR_KEY_SZ_SHIFT;
|
||||||
|
- else if (aes_key_size == AES_KEYSIZE_256)
|
||||||
|
- cfg |= ENCR_KEY_SZ_AES256 << ENCR_KEY_SZ_SHIFT;
|
||||||
|
- }
|
||||||
|
+ config = (beats << REQ_SIZE_SHIFT) & REQ_SIZE_MASK;
|
||||||
|
+ config |= BIT(MASK_DOUT_INTR_SHIFT) | BIT(MASK_DIN_INTR_SHIFT) |
|
||||||
|
+ BIT(MASK_OP_DONE_INTR_SHIFT) | BIT(MASK_ERR_INTR_SHIFT);
|
||||||
|
+ config |= (pipe_pair << PIPE_SET_SELECT_SHIFT) & PIPE_SET_SELECT_MASK;
|
||||||
|
+ config &= ~HIGH_SPD_EN_N_SHIFT;
|
||||||
|
|
||||||
|
- if (IS_AES(flags))
|
||||||
|
- cfg |= ENCR_ALG_AES << ENCR_ALG_SHIFT;
|
||||||
|
- else if (IS_DES(flags) || IS_3DES(flags))
|
||||||
|
- cfg |= ENCR_ALG_DES << ENCR_ALG_SHIFT;
|
||||||
|
+ if (little)
|
||||||
|
+ config |= BIT(LITTLE_ENDIAN_MODE_SHIFT);
|
||||||
|
|
||||||
|
- if (IS_DES(flags))
|
||||||
|
- cfg |= ENCR_KEY_SZ_DES << ENCR_KEY_SZ_SHIFT;
|
||||||
|
+ return config;
|
||||||
|
+}
|
||||||
|
|
||||||
|
- if (IS_3DES(flags))
|
||||||
|
- cfg |= ENCR_KEY_SZ_3DES << ENCR_KEY_SZ_SHIFT;
|
||||||
|
+void qce_cpu_to_be32p_array(__be32 *dst, const u8 *src, unsigned int len)
|
||||||
|
+{
|
||||||
|
+ __be32 *d = dst;
|
||||||
|
+ const u8 *s = src;
|
||||||
|
+ unsigned int n;
|
||||||
|
|
||||||
|
- switch (flags & QCE_MODE_MASK) {
|
||||||
|
- case QCE_MODE_ECB:
|
||||||
|
- cfg |= ENCR_MODE_ECB << ENCR_MODE_SHIFT;
|
||||||
|
- break;
|
||||||
|
- case QCE_MODE_CBC:
|
||||||
|
- cfg |= ENCR_MODE_CBC << ENCR_MODE_SHIFT;
|
||||||
|
- break;
|
||||||
|
- case QCE_MODE_CTR:
|
||||||
|
- cfg |= ENCR_MODE_CTR << ENCR_MODE_SHIFT;
|
||||||
|
- break;
|
||||||
|
- case QCE_MODE_XTS:
|
||||||
|
- cfg |= ENCR_MODE_XTS << ENCR_MODE_SHIFT;
|
||||||
|
- break;
|
||||||
|
- case QCE_MODE_CCM:
|
||||||
|
- cfg |= ENCR_MODE_CCM << ENCR_MODE_SHIFT;
|
||||||
|
- cfg |= LAST_CCM_XFR << LAST_CCM_SHIFT;
|
||||||
|
- break;
|
||||||
|
- default:
|
||||||
|
- return ~0;
|
||||||
|
+ n = len / sizeof(u32);
|
||||||
|
+ for (; n > 0; n--) {
|
||||||
|
+ *d = cpu_to_be32p((const __u32 *) s);
|
||||||
|
+ s += sizeof(__u32);
|
||||||
|
+ d++;
|
||||||
|
}
|
||||||
|
+}
|
||||||
|
|
||||||
|
- return cfg;
|
||||||
|
+static void qce_setup_config(struct qce_device *qce)
|
||||||
|
+{
|
||||||
|
+ u32 config;
|
||||||
|
+
|
||||||
|
+ /* get big endianness */
|
||||||
|
+ config = qce_config_reg(qce, 0);
|
||||||
|
+
|
||||||
|
+ /* clear status */
|
||||||
|
+ qce_write(qce, REG_STATUS, 0);
|
||||||
|
+ qce_write(qce, REG_CONFIG, config);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline void qce_crypto_go(struct qce_device *qce)
|
||||||
|
+{
|
||||||
|
+ qce_write(qce, REG_GOPROC, BIT(GO_SHIFT) | BIT(RESULTS_DUMP_SHIFT));
|
||||||
|
}
|
||||||
|
|
||||||
|
+#ifdef CONFIG_CRYPTO_DEV_QCE_SHA
|
||||||
|
static u32 qce_auth_cfg(unsigned long flags, u32 key_size)
|
||||||
|
{
|
||||||
|
u32 cfg = 0;
|
||||||
|
@@ -135,88 +139,6 @@ static u32 qce_auth_cfg(unsigned long fl
|
||||||
|
return cfg;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static u32 qce_config_reg(struct qce_device *qce, int little)
|
||||||
|
-{
|
||||||
|
- u32 beats = (qce->burst_size >> 3) - 1;
|
||||||
|
- u32 pipe_pair = qce->pipe_pair_id;
|
||||||
|
- u32 config;
|
||||||
|
-
|
||||||
|
- config = (beats << REQ_SIZE_SHIFT) & REQ_SIZE_MASK;
|
||||||
|
- config |= BIT(MASK_DOUT_INTR_SHIFT) | BIT(MASK_DIN_INTR_SHIFT) |
|
||||||
|
- BIT(MASK_OP_DONE_INTR_SHIFT) | BIT(MASK_ERR_INTR_SHIFT);
|
||||||
|
- config |= (pipe_pair << PIPE_SET_SELECT_SHIFT) & PIPE_SET_SELECT_MASK;
|
||||||
|
- config &= ~HIGH_SPD_EN_N_SHIFT;
|
||||||
|
-
|
||||||
|
- if (little)
|
||||||
|
- config |= BIT(LITTLE_ENDIAN_MODE_SHIFT);
|
||||||
|
-
|
||||||
|
- return config;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-void qce_cpu_to_be32p_array(__be32 *dst, const u8 *src, unsigned int len)
|
||||||
|
-{
|
||||||
|
- __be32 *d = dst;
|
||||||
|
- const u8 *s = src;
|
||||||
|
- unsigned int n;
|
||||||
|
-
|
||||||
|
- n = len / sizeof(u32);
|
||||||
|
- for (; n > 0; n--) {
|
||||||
|
- *d = cpu_to_be32p((const __u32 *) s);
|
||||||
|
- s += sizeof(__u32);
|
||||||
|
- d++;
|
||||||
|
- }
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static void qce_xts_swapiv(__be32 *dst, const u8 *src, unsigned int ivsize)
|
||||||
|
-{
|
||||||
|
- u8 swap[QCE_AES_IV_LENGTH];
|
||||||
|
- u32 i, j;
|
||||||
|
-
|
||||||
|
- if (ivsize > QCE_AES_IV_LENGTH)
|
||||||
|
- return;
|
||||||
|
-
|
||||||
|
- memset(swap, 0, QCE_AES_IV_LENGTH);
|
||||||
|
-
|
||||||
|
- for (i = (QCE_AES_IV_LENGTH - ivsize), j = ivsize - 1;
|
||||||
|
- i < QCE_AES_IV_LENGTH; i++, j--)
|
||||||
|
- swap[i] = src[j];
|
||||||
|
-
|
||||||
|
- qce_cpu_to_be32p_array(dst, swap, QCE_AES_IV_LENGTH);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static void qce_xtskey(struct qce_device *qce, const u8 *enckey,
|
||||||
|
- unsigned int enckeylen, unsigned int cryptlen)
|
||||||
|
-{
|
||||||
|
- u32 xtskey[QCE_MAX_CIPHER_KEY_SIZE / sizeof(u32)] = {0};
|
||||||
|
- unsigned int xtsklen = enckeylen / (2 * sizeof(u32));
|
||||||
|
- unsigned int xtsdusize;
|
||||||
|
-
|
||||||
|
- qce_cpu_to_be32p_array((__be32 *)xtskey, enckey + enckeylen / 2,
|
||||||
|
- enckeylen / 2);
|
||||||
|
- qce_write_array(qce, REG_ENCR_XTS_KEY0, xtskey, xtsklen);
|
||||||
|
-
|
||||||
|
- /* xts du size 512B */
|
||||||
|
- xtsdusize = min_t(u32, QCE_SECTOR_SIZE, cryptlen);
|
||||||
|
- qce_write(qce, REG_ENCR_XTS_DU_SIZE, xtsdusize);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static void qce_setup_config(struct qce_device *qce)
|
||||||
|
-{
|
||||||
|
- u32 config;
|
||||||
|
-
|
||||||
|
- /* get big endianness */
|
||||||
|
- config = qce_config_reg(qce, 0);
|
||||||
|
-
|
||||||
|
- /* clear status */
|
||||||
|
- qce_write(qce, REG_STATUS, 0);
|
||||||
|
- qce_write(qce, REG_CONFIG, config);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static inline void qce_crypto_go(struct qce_device *qce)
|
||||||
|
-{
|
||||||
|
- qce_write(qce, REG_GOPROC, BIT(GO_SHIFT) | BIT(RESULTS_DUMP_SHIFT));
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static int qce_setup_regs_ahash(struct crypto_async_request *async_req,
|
||||||
|
u32 totallen, u32 offset)
|
||||||
|
{
|
||||||
|
@@ -301,6 +223,87 @@ go_proc:
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+#ifdef CONFIG_CRYPTO_DEV_QCE_SKCIPHER
|
||||||
|
+static u32 qce_encr_cfg(unsigned long flags, u32 aes_key_size)
|
||||||
|
+{
|
||||||
|
+ u32 cfg = 0;
|
||||||
|
+
|
||||||
|
+ if (IS_AES(flags)) {
|
||||||
|
+ if (aes_key_size == AES_KEYSIZE_128)
|
||||||
|
+ cfg |= ENCR_KEY_SZ_AES128 << ENCR_KEY_SZ_SHIFT;
|
||||||
|
+ else if (aes_key_size == AES_KEYSIZE_256)
|
||||||
|
+ cfg |= ENCR_KEY_SZ_AES256 << ENCR_KEY_SZ_SHIFT;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (IS_AES(flags))
|
||||||
|
+ cfg |= ENCR_ALG_AES << ENCR_ALG_SHIFT;
|
||||||
|
+ else if (IS_DES(flags) || IS_3DES(flags))
|
||||||
|
+ cfg |= ENCR_ALG_DES << ENCR_ALG_SHIFT;
|
||||||
|
+
|
||||||
|
+ if (IS_DES(flags))
|
||||||
|
+ cfg |= ENCR_KEY_SZ_DES << ENCR_KEY_SZ_SHIFT;
|
||||||
|
+
|
||||||
|
+ if (IS_3DES(flags))
|
||||||
|
+ cfg |= ENCR_KEY_SZ_3DES << ENCR_KEY_SZ_SHIFT;
|
||||||
|
+
|
||||||
|
+ switch (flags & QCE_MODE_MASK) {
|
||||||
|
+ case QCE_MODE_ECB:
|
||||||
|
+ cfg |= ENCR_MODE_ECB << ENCR_MODE_SHIFT;
|
||||||
|
+ break;
|
||||||
|
+ case QCE_MODE_CBC:
|
||||||
|
+ cfg |= ENCR_MODE_CBC << ENCR_MODE_SHIFT;
|
||||||
|
+ break;
|
||||||
|
+ case QCE_MODE_CTR:
|
||||||
|
+ cfg |= ENCR_MODE_CTR << ENCR_MODE_SHIFT;
|
||||||
|
+ break;
|
||||||
|
+ case QCE_MODE_XTS:
|
||||||
|
+ cfg |= ENCR_MODE_XTS << ENCR_MODE_SHIFT;
|
||||||
|
+ break;
|
||||||
|
+ case QCE_MODE_CCM:
|
||||||
|
+ cfg |= ENCR_MODE_CCM << ENCR_MODE_SHIFT;
|
||||||
|
+ cfg |= LAST_CCM_XFR << LAST_CCM_SHIFT;
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ return ~0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return cfg;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void qce_xts_swapiv(__be32 *dst, const u8 *src, unsigned int ivsize)
|
||||||
|
+{
|
||||||
|
+ u8 swap[QCE_AES_IV_LENGTH];
|
||||||
|
+ u32 i, j;
|
||||||
|
+
|
||||||
|
+ if (ivsize > QCE_AES_IV_LENGTH)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ memset(swap, 0, QCE_AES_IV_LENGTH);
|
||||||
|
+
|
||||||
|
+ for (i = (QCE_AES_IV_LENGTH - ivsize), j = ivsize - 1;
|
||||||
|
+ i < QCE_AES_IV_LENGTH; i++, j--)
|
||||||
|
+ swap[i] = src[j];
|
||||||
|
+
|
||||||
|
+ qce_cpu_to_be32p_array(dst, swap, QCE_AES_IV_LENGTH);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void qce_xtskey(struct qce_device *qce, const u8 *enckey,
|
||||||
|
+ unsigned int enckeylen, unsigned int cryptlen)
|
||||||
|
+{
|
||||||
|
+ u32 xtskey[QCE_MAX_CIPHER_KEY_SIZE / sizeof(u32)] = {0};
|
||||||
|
+ unsigned int xtsklen = enckeylen / (2 * sizeof(u32));
|
||||||
|
+ unsigned int xtsdusize;
|
||||||
|
+
|
||||||
|
+ qce_cpu_to_be32p_array((__be32 *)xtskey, enckey + enckeylen / 2,
|
||||||
|
+ enckeylen / 2);
|
||||||
|
+ qce_write_array(qce, REG_ENCR_XTS_KEY0, xtskey, xtsklen);
|
||||||
|
+
|
||||||
|
+ /* xts du size 512B */
|
||||||
|
+ xtsdusize = min_t(u32, QCE_SECTOR_SIZE, cryptlen);
|
||||||
|
+ qce_write(qce, REG_ENCR_XTS_DU_SIZE, xtsdusize);
|
||||||
|
+}
|
||||||
|
|
||||||
|
static int qce_setup_regs_skcipher(struct crypto_async_request *async_req,
|
||||||
|
u32 totallen, u32 offset)
|
||||||
|
@@ -382,15 +385,20 @@ static int qce_setup_regs_skcipher(struc
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
int qce_start(struct crypto_async_request *async_req, u32 type, u32 totallen,
|
||||||
|
u32 offset)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
+#ifdef CONFIG_CRYPTO_DEV_QCE_SKCIPHER
|
||||||
|
case CRYPTO_ALG_TYPE_SKCIPHER:
|
||||||
|
return qce_setup_regs_skcipher(async_req, totallen, offset);
|
||||||
|
+#endif
|
||||||
|
+#ifdef CONFIG_CRYPTO_DEV_QCE_SHA
|
||||||
|
case CRYPTO_ALG_TYPE_AHASH:
|
||||||
|
return qce_setup_regs_ahash(async_req, totallen, offset);
|
||||||
|
+#endif
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
--- a/drivers/crypto/qce/core.c
|
||||||
|
+++ b/drivers/crypto/qce/core.c
|
||||||
|
@@ -22,8 +22,12 @@
|
||||||
|
#define QCE_QUEUE_LENGTH 1
|
||||||
|
|
||||||
|
static const struct qce_algo_ops *qce_ops[] = {
|
||||||
|
+#ifdef CONFIG_CRYPTO_DEV_QCE_SKCIPHER
|
||||||
|
&skcipher_ops,
|
||||||
|
+#endif
|
||||||
|
+#ifdef CONFIG_CRYPTO_DEV_QCE_SHA
|
||||||
|
&ahash_ops,
|
||||||
|
+#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
static void qce_unregister_algs(struct qce_device *qce)
|
|
@ -0,0 +1,38 @@
|
||||||
|
From 8a4540321e8bcf7a5b485c332a2e78f3501c78ed Mon Sep 17 00:00:00 2001
|
||||||
|
From: Robert Marko <robimarko@gmail.com>
|
||||||
|
Date: Thu, 29 Nov 2018 22:29:36 +0100
|
||||||
|
Subject: [PATCH] ipq40xx: Fix booting secondary cores
|
||||||
|
|
||||||
|
Add the second part of old 071-qcom-ipq4019-use-v2-of-the-kpss-bringup-mechanism.patch
|
||||||
|
We dont modify the patch itself as its upstream and this change is not.
|
||||||
|
|
||||||
|
Originally added by Mantas Pucka Mantas Pucka <mantas@8devices.com>
|
||||||
|
|
||||||
|
Signed-off-by: Robert Marko <robimarko@gmail.com>
|
||||||
|
---
|
||||||
|
arch/arm/boot/dts/qcom-ipq4019.dtsi | 7 +++++++
|
||||||
|
1 file changed, 7 insertions(+)
|
||||||
|
|
||||||
|
--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi
|
||||||
|
+++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi
|
||||||
|
@@ -102,6 +102,7 @@
|
||||||
|
L2: l2-cache {
|
||||||
|
compatible = "cache";
|
||||||
|
cache-level = <2>;
|
||||||
|
+ qcom,saw = <&saw_l2>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -341,6 +342,12 @@
|
||||||
|
regulator;
|
||||||
|
};
|
||||||
|
|
||||||
|
+ saw_l2: regulator@b012000 {
|
||||||
|
+ compatible = "qcom,saw2";
|
||||||
|
+ reg = <0xb012000 0x1000>;
|
||||||
|
+ regulator;
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
blsp1_uart1: serial@78af000 {
|
||||||
|
compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
|
||||||
|
reg = <0x78af000 0x200>;
|
|
@ -0,0 +1,36 @@
|
||||||
|
From 89b43d59ec8c9cda588555eb1f2754dd19ef5144 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Lamparter <chunkeey@gmail.com>
|
||||||
|
Date: Sun, 22 Jul 2018 12:07:57 +0200
|
||||||
|
Subject: [PATCH 8/8] ARM: qcom: Add IPQ4019 SoC support
|
||||||
|
|
||||||
|
Add support for the Qualcomm Atheros IPQ4019 SoC.
|
||||||
|
|
||||||
|
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
|
||||||
|
Signed-off-by: John Crispin <john@phrozen.org>
|
||||||
|
---
|
||||||
|
arch/arm/Makefile | 1 +
|
||||||
|
arch/arm/mach-qcom/Kconfig | 5 +++++
|
||||||
|
2 files changed, 6 insertions(+)
|
||||||
|
|
||||||
|
--- a/arch/arm/Makefile
|
||||||
|
+++ b/arch/arm/Makefile
|
||||||
|
@@ -156,6 +156,7 @@ textofs-$(CONFIG_ARCH_MSM8X60) := 0x0020
|
||||||
|
textofs-$(CONFIG_ARCH_MSM8960) := 0x00208000
|
||||||
|
textofs-$(CONFIG_ARCH_MESON) := 0x00208000
|
||||||
|
textofs-$(CONFIG_ARCH_AXXIA) := 0x00308000
|
||||||
|
+textofs-$(CONFIG_ARCH_IPQ40XX) := 0x00208000
|
||||||
|
|
||||||
|
# Machine directory name. This list is sorted alphanumerically
|
||||||
|
# by CONFIG_* macro name.
|
||||||
|
--- a/arch/arm/mach-qcom/Kconfig
|
||||||
|
+++ b/arch/arm/mach-qcom/Kconfig
|
||||||
|
@@ -28,4 +28,9 @@ config ARCH_MDM9615
|
||||||
|
bool "Enable support for MDM9615"
|
||||||
|
select CLKSRC_QCOM
|
||||||
|
|
||||||
|
+config ARCH_IPQ40XX
|
||||||
|
+ bool "Enable support for IPQ40XX"
|
||||||
|
+ select CLKSRC_QCOM
|
||||||
|
+ select HAVE_ARM_ARCH_TIMER
|
||||||
|
+
|
||||||
|
endif
|
|
@ -0,0 +1,38 @@
|
||||||
|
From 5f01733dc755dfadfa51b7b3c6c160e632fc6002 Mon Sep 17 00:00:00 2001
|
||||||
|
From: John Crispin <john@phrozen.org>
|
||||||
|
Date: Tue, 24 Jul 2018 15:09:36 +0200
|
||||||
|
Subject: [PATCH 1/3] dt-bindings: phy-qcom-ipq4019-usb: add binding document
|
||||||
|
|
||||||
|
This patch adds the binding documentation for the HS/SS USB PHY found
|
||||||
|
inside Qualcom Dakota SoCs.
|
||||||
|
|
||||||
|
Signed-off-by: John Crispin <john@phrozen.org>
|
||||||
|
---
|
||||||
|
.../bindings/phy/phy-qcom-ipq4019-usb.txt | 21 +++++++++++++++++++++
|
||||||
|
1 file changed, 21 insertions(+)
|
||||||
|
create mode 100644 Documentation/devicetree/bindings/phy/phy-qcom-ipq4019-usb.txt
|
||||||
|
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/Documentation/devicetree/bindings/phy/phy-qcom-ipq4019-usb.txt
|
||||||
|
@@ -0,0 +1,21 @@
|
||||||
|
+Qualcom Dakota HS/SS USB PHY
|
||||||
|
+
|
||||||
|
+Required properties:
|
||||||
|
+ - compatible: "qcom,usb-ss-ipq4019-phy",
|
||||||
|
+ "qcom,usb-hs-ipq4019-phy"
|
||||||
|
+ - reg: offset and length of the registers
|
||||||
|
+ - #phy-cells: should be 0
|
||||||
|
+ - resets: the reset controllers as listed below
|
||||||
|
+ - reset-names: the names of the reset controllers
|
||||||
|
+ "por_rst" - the POR reset line for SS and HS phys
|
||||||
|
+ "srif_rst" - the SRIF reset line for HS phys
|
||||||
|
+Example:
|
||||||
|
+
|
||||||
|
+hsphy@a8000 {
|
||||||
|
+ compatible = "qcom,usb-hs-ipq4019-phy";
|
||||||
|
+ phy-cells = <0>;
|
||||||
|
+ reg = <0xa8000 0x40>;
|
||||||
|
+ resets = <&gcc USB2_HSPHY_POR_ARES>,
|
||||||
|
+ <&gcc USB2_HSPHY_S_ARES>;
|
||||||
|
+ reset-names = "por_rst", "srif_rst";
|
||||||
|
+};
|
|
@ -0,0 +1,234 @@
|
||||||
|
From 633f0e08498aebfdb932bd71319b4cb136709499 Mon Sep 17 00:00:00 2001
|
||||||
|
From: John Crispin <john@phrozen.org>
|
||||||
|
Date: Tue, 24 Jul 2018 14:45:49 +0200
|
||||||
|
Subject: [PATCH 2/3] phy: qcom-ipq4019-usb: add driver for QCOM/IPQ4019
|
||||||
|
|
||||||
|
Add a driver to setup the USB phy on Qualcom Dakota SoCs.
|
||||||
|
The driver sets up HS and SS phys. In case of HS some magic values need to
|
||||||
|
be written to magic offsets. These were taken from the SDK driver.
|
||||||
|
|
||||||
|
Signed-off-by: John Crispin <john@phrozen.org>
|
||||||
|
---
|
||||||
|
drivers/phy/qualcomm/Kconfig | 7 ++
|
||||||
|
drivers/phy/qualcomm/Makefile | 1 +
|
||||||
|
drivers/phy/qualcomm/phy-qcom-ipq4019-usb.c | 188 ++++++++++++++++++++++++++++
|
||||||
|
3 files changed, 196 insertions(+)
|
||||||
|
create mode 100644 drivers/phy/qualcomm/phy-qcom-ipq4019-usb.c
|
||||||
|
|
||||||
|
--- a/drivers/phy/qualcomm/Kconfig
|
||||||
|
+++ b/drivers/phy/qualcomm/Kconfig
|
||||||
|
@@ -18,6 +18,13 @@ config PHY_QCOM_APQ8064_SATA
|
||||||
|
depends on OF
|
||||||
|
select GENERIC_PHY
|
||||||
|
|
||||||
|
+config PHY_QCOM_IPQ4019_USB
|
||||||
|
+ tristate "Qualcomm IPQ4019 USB PHY module"
|
||||||
|
+ depends on OF && ARCH_QCOM
|
||||||
|
+ select GENERIC_PHY
|
||||||
|
+ help
|
||||||
|
+ Support for the USB PHY on QCOM IPQ4019/Dakota chipsets.
|
||||||
|
+
|
||||||
|
config PHY_QCOM_IPQ806X_SATA
|
||||||
|
tristate "Qualcomm IPQ806x SATA SerDes/PHY driver"
|
||||||
|
depends on ARCH_QCOM
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/drivers/phy/qualcomm/phy-qcom-ipq4019-usb.c
|
||||||
|
@@ -0,0 +1,188 @@
|
||||||
|
+/*
|
||||||
|
+ * Copyright (C) 2018 John Crispin <john@phrozen.org>
|
||||||
|
+ *
|
||||||
|
+ * Based on code from
|
||||||
|
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
|
||||||
|
+ *
|
||||||
|
+ * This program is free software; you can redistribute it and/or modify
|
||||||
|
+ * it under the terms of the GNU General Public License as published by
|
||||||
|
+ * the Free Software Foundation; either version 2 of the License, or
|
||||||
|
+ * (at your option) any later version.
|
||||||
|
+ *
|
||||||
|
+ * This program is distributed in the hope that it will be useful,
|
||||||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
+ * GNU General Public License for more details.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include <linux/delay.h>
|
||||||
|
+#include <linux/err.h>
|
||||||
|
+#include <linux/io.h>
|
||||||
|
+#include <linux/kernel.h>
|
||||||
|
+#include <linux/module.h>
|
||||||
|
+#include <linux/mutex.h>
|
||||||
|
+#include <linux/of_platform.h>
|
||||||
|
+#include <linux/phy/phy.h>
|
||||||
|
+#include <linux/platform_device.h>
|
||||||
|
+#include <linux/reset.h>
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Magic registers copied from the SDK driver code
|
||||||
|
+ */
|
||||||
|
+#define PHY_CTRL0_ADDR 0x000
|
||||||
|
+#define PHY_CTRL1_ADDR 0x004
|
||||||
|
+#define PHY_CTRL2_ADDR 0x008
|
||||||
|
+#define PHY_CTRL3_ADDR 0x00C
|
||||||
|
+#define PHY_CTRL4_ADDR 0x010
|
||||||
|
+#define PHY_MISC_ADDR 0x024
|
||||||
|
+#define PHY_IPG_ADDR 0x030
|
||||||
|
+
|
||||||
|
+#define PHY_CTRL0_VAL 0xA4600015
|
||||||
|
+#define PHY_CTRL1_VAL 0x09500000
|
||||||
|
+#define PHY_CTRL2_VAL 0x00058180
|
||||||
|
+#define PHY_CTRL3_VAL 0x6DB6DCD6
|
||||||
|
+#define PHY_CTRL4_VAL 0x836DB6DB
|
||||||
|
+#define PHY_MISC_VAL 0x3803FB0C
|
||||||
|
+#define PHY_IPG_VAL 0x47323232
|
||||||
|
+
|
||||||
|
+struct ipq4019_usb_phy {
|
||||||
|
+ struct device *dev;
|
||||||
|
+ struct phy *phy;
|
||||||
|
+ void __iomem *base;
|
||||||
|
+ struct reset_control *por_rst;
|
||||||
|
+ struct reset_control *srif_rst;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int ipq4019_ss_phy_power_off(struct phy *_phy)
|
||||||
|
+{
|
||||||
|
+ struct ipq4019_usb_phy *phy = phy_get_drvdata(_phy);
|
||||||
|
+
|
||||||
|
+ reset_control_assert(phy->por_rst);
|
||||||
|
+ msleep(10);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int ipq4019_ss_phy_power_on(struct phy *_phy)
|
||||||
|
+{
|
||||||
|
+ struct ipq4019_usb_phy *phy = phy_get_drvdata(_phy);
|
||||||
|
+
|
||||||
|
+ ipq4019_ss_phy_power_off(_phy);
|
||||||
|
+
|
||||||
|
+ reset_control_deassert(phy->por_rst);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct phy_ops ipq4019_usb_ss_phy_ops = {
|
||||||
|
+ .power_on = ipq4019_ss_phy_power_on,
|
||||||
|
+ .power_off = ipq4019_ss_phy_power_off,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int ipq4019_hs_phy_power_off(struct phy *_phy)
|
||||||
|
+{
|
||||||
|
+ struct ipq4019_usb_phy *phy = phy_get_drvdata(_phy);
|
||||||
|
+
|
||||||
|
+ reset_control_assert(phy->por_rst);
|
||||||
|
+ msleep(10);
|
||||||
|
+
|
||||||
|
+ reset_control_assert(phy->srif_rst);
|
||||||
|
+ msleep(10);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int ipq4019_hs_phy_power_on(struct phy *_phy)
|
||||||
|
+{
|
||||||
|
+ struct ipq4019_usb_phy *phy = phy_get_drvdata(_phy);
|
||||||
|
+
|
||||||
|
+ ipq4019_hs_phy_power_off(_phy);
|
||||||
|
+
|
||||||
|
+ reset_control_deassert(phy->srif_rst);
|
||||||
|
+ msleep(10);
|
||||||
|
+
|
||||||
|
+ writel(PHY_CTRL0_VAL, phy->base + PHY_CTRL0_ADDR);
|
||||||
|
+ writel(PHY_CTRL1_VAL, phy->base + PHY_CTRL1_ADDR);
|
||||||
|
+ writel(PHY_CTRL2_VAL, phy->base + PHY_CTRL2_ADDR);
|
||||||
|
+ writel(PHY_CTRL3_VAL, phy->base + PHY_CTRL3_ADDR);
|
||||||
|
+ writel(PHY_CTRL4_VAL, phy->base + PHY_CTRL4_ADDR);
|
||||||
|
+ writel(PHY_MISC_VAL, phy->base + PHY_MISC_ADDR);
|
||||||
|
+ writel(PHY_IPG_VAL, phy->base + PHY_IPG_ADDR);
|
||||||
|
+ msleep(10);
|
||||||
|
+
|
||||||
|
+ reset_control_deassert(phy->por_rst);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct phy_ops ipq4019_usb_hs_phy_ops = {
|
||||||
|
+ .power_on = ipq4019_hs_phy_power_on,
|
||||||
|
+ .power_off = ipq4019_hs_phy_power_off,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static const struct of_device_id ipq4019_usb_phy_of_match[] = {
|
||||||
|
+ { .compatible = "qcom,usb-hs-ipq4019-phy", .data = &ipq4019_usb_hs_phy_ops},
|
||||||
|
+ { .compatible = "qcom,usb-ss-ipq4019-phy", .data = &ipq4019_usb_ss_phy_ops},
|
||||||
|
+ { },
|
||||||
|
+};
|
||||||
|
+MODULE_DEVICE_TABLE(of, ipq4019_usb_phy_of_match);
|
||||||
|
+
|
||||||
|
+static int ipq4019_usb_phy_probe(struct platform_device *pdev)
|
||||||
|
+{
|
||||||
|
+ struct device *dev = &pdev->dev;
|
||||||
|
+ struct resource *res;
|
||||||
|
+ struct phy_provider *phy_provider;
|
||||||
|
+ struct ipq4019_usb_phy *phy;
|
||||||
|
+ const struct of_device_id *match;
|
||||||
|
+
|
||||||
|
+ match = of_match_device(ipq4019_usb_phy_of_match, &pdev->dev);
|
||||||
|
+ if (!match)
|
||||||
|
+ return -ENODEV;
|
||||||
|
+
|
||||||
|
+ phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
|
||||||
|
+ if (!phy)
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+
|
||||||
|
+ phy->dev = &pdev->dev;
|
||||||
|
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
+ phy->base = devm_ioremap_resource(&pdev->dev, res);
|
||||||
|
+ if (IS_ERR(phy->base)) {
|
||||||
|
+ dev_err(dev, "failed to remap register memory\n");
|
||||||
|
+ return PTR_ERR(phy->base);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ phy->por_rst = devm_reset_control_get(phy->dev, "por_rst");
|
||||||
|
+ if (IS_ERR(phy->por_rst)) {
|
||||||
|
+ if (PTR_ERR(phy->por_rst) != -EPROBE_DEFER)
|
||||||
|
+ dev_err(dev, "POR reset is missing\n");
|
||||||
|
+ return PTR_ERR(phy->por_rst);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ phy->srif_rst = devm_reset_control_get_optional(phy->dev, "srif_rst");
|
||||||
|
+ if (IS_ERR(phy->srif_rst))
|
||||||
|
+ return PTR_ERR(phy->srif_rst);
|
||||||
|
+
|
||||||
|
+ phy->phy = devm_phy_create(dev, NULL, match->data);
|
||||||
|
+ if (IS_ERR(phy->phy)) {
|
||||||
|
+ dev_err(dev, "failed to create PHY\n");
|
||||||
|
+ return PTR_ERR(phy->phy);
|
||||||
|
+ }
|
||||||
|
+ phy_set_drvdata(phy->phy, phy);
|
||||||
|
+
|
||||||
|
+ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
|
||||||
|
+
|
||||||
|
+ return PTR_ERR_OR_ZERO(phy_provider);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct platform_driver ipq4019_usb_phy_driver = {
|
||||||
|
+ .probe = ipq4019_usb_phy_probe,
|
||||||
|
+ .driver = {
|
||||||
|
+ .of_match_table = ipq4019_usb_phy_of_match,
|
||||||
|
+ .name = "ipq4019-usb-phy",
|
||||||
|
+ }
|
||||||
|
+};
|
||||||
|
+module_platform_driver(ipq4019_usb_phy_driver);
|
||||||
|
+
|
||||||
|
+MODULE_DESCRIPTION("QCOM/IPQ4019 USB phy driver");
|
||||||
|
+MODULE_AUTHOR("John Crispin <john@phrozen.org>");
|
||||||
|
+MODULE_LICENSE("GPL v2");
|
||||||
|
--- a/drivers/phy/qualcomm/Makefile
|
||||||
|
+++ b/drivers/phy/qualcomm/Makefile
|
||||||
|
@@ -1,6 +1,7 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
obj-$(CONFIG_PHY_ATH79_USB) += phy-ath79-usb.o
|
||||||
|
obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o
|
||||||
|
+obj-$(CONFIG_PHY_QCOM_IPQ4019_USB) += phy-qcom-ipq4019-usb.o
|
||||||
|
obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o
|
||||||
|
obj-$(CONFIG_PHY_QCOM_PCIE2) += phy-qcom-pcie2.o
|
||||||
|
obj-$(CONFIG_PHY_QCOM_QMP) += phy-qcom-qmp.o
|
|
@ -0,0 +1,123 @@
|
||||||
|
From 1fc7d5523e21ed140fed43c4dde011a3b6d9ba08 Mon Sep 17 00:00:00 2001
|
||||||
|
From: John Crispin <john@phrozen.org>
|
||||||
|
Date: Tue, 24 Jul 2018 14:47:55 +0200
|
||||||
|
Subject: [PATCH 3/3] qcom: ipq4019: add USB devicetree nodes
|
||||||
|
|
||||||
|
This patch makes USB work on the Dakota EVB.
|
||||||
|
|
||||||
|
Signed-off-by: John Crispin <john@phrozen.org>
|
||||||
|
---
|
||||||
|
arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi | 20 ++++++++
|
||||||
|
arch/arm/boot/dts/qcom-ipq4019.dtsi | 74 +++++++++++++++++++++++++++
|
||||||
|
2 files changed, 94 insertions(+)
|
||||||
|
|
||||||
|
--- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi
|
||||||
|
+++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi
|
||||||
|
@@ -109,5 +109,25 @@
|
||||||
|
wifi@a800000 {
|
||||||
|
status = "ok";
|
||||||
|
};
|
||||||
|
+
|
||||||
|
+ usb3_ss_phy: ssphy@9a000 {
|
||||||
|
+ status = "okay";
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ usb3_hs_phy: hsphy@a6000 {
|
||||||
|
+ status = "okay";
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ usb3: usb3@8af8800 {
|
||||||
|
+ status = "okay";
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ usb2_hs_phy: hsphy@a8000 {
|
||||||
|
+ status = "okay";
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ usb2: usb2@60f8800 {
|
||||||
|
+ status = "okay";
|
||||||
|
+ };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi
|
||||||
|
+++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi
|
||||||
|
@@ -563,5 +563,79 @@
|
||||||
|
"legacy";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
+
|
||||||
|
+ usb3_ss_phy: ssphy@9a000 {
|
||||||
|
+ compatible = "qcom,usb-ss-ipq4019-phy";
|
||||||
|
+ #phy-cells = <0>;
|
||||||
|
+ reg = <0x9a000 0x800>;
|
||||||
|
+ reg-names = "phy_base";
|
||||||
|
+ resets = <&gcc USB3_UNIPHY_PHY_ARES>;
|
||||||
|
+ reset-names = "por_rst";
|
||||||
|
+ status = "disabled";
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ usb3_hs_phy: hsphy@a6000 {
|
||||||
|
+ compatible = "qcom,usb-hs-ipq4019-phy";
|
||||||
|
+ #phy-cells = <0>;
|
||||||
|
+ reg = <0xa6000 0x40>;
|
||||||
|
+ reg-names = "phy_base";
|
||||||
|
+ resets = <&gcc USB3_HSPHY_POR_ARES>, <&gcc USB3_HSPHY_S_ARES>;
|
||||||
|
+ reset-names = "por_rst", "srif_rst";
|
||||||
|
+ status = "disabled";
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ usb3@8af8800 {
|
||||||
|
+ compatible = "qcom,dwc3";
|
||||||
|
+ reg = <0x8af8800 0x100>;
|
||||||
|
+ #address-cells = <1>;
|
||||||
|
+ #size-cells = <1>;
|
||||||
|
+ clocks = <&gcc GCC_USB3_MASTER_CLK>,
|
||||||
|
+ <&gcc GCC_USB3_SLEEP_CLK>,
|
||||||
|
+ <&gcc GCC_USB3_MOCK_UTMI_CLK>;
|
||||||
|
+ clock-names = "master", "sleep", "mock_utmi";
|
||||||
|
+ ranges;
|
||||||
|
+ status = "disabled";
|
||||||
|
+
|
||||||
|
+ dwc3@8a00000 {
|
||||||
|
+ compatible = "snps,dwc3";
|
||||||
|
+ reg = <0x8a00000 0xf8000>;
|
||||||
|
+ interrupts = <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
+ phys = <&usb3_hs_phy>, <&usb3_ss_phy>;
|
||||||
|
+ phy-names = "usb2-phy", "usb3-phy";
|
||||||
|
+ dr_mode = "host";
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ usb2_hs_phy: hsphy@a8000 {
|
||||||
|
+ compatible = "qcom,usb-hs-ipq4019-phy";
|
||||||
|
+ #phy-cells = <0>;
|
||||||
|
+ reg = <0xa8000 0x40>;
|
||||||
|
+ reg-names = "phy_base";
|
||||||
|
+ resets = <&gcc USB2_HSPHY_POR_ARES>, <&gcc USB2_HSPHY_S_ARES>;
|
||||||
|
+ reset-names = "por_rst", "srif_rst";
|
||||||
|
+ status = "disabled";
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ usb2@60f8800 {
|
||||||
|
+ compatible = "qcom,dwc3";
|
||||||
|
+ reg = <0x60f8800 0x100>;
|
||||||
|
+ #address-cells = <1>;
|
||||||
|
+ #size-cells = <1>;
|
||||||
|
+ clocks = <&gcc GCC_USB2_MASTER_CLK>,
|
||||||
|
+ <&gcc GCC_USB2_SLEEP_CLK>,
|
||||||
|
+ <&gcc GCC_USB2_MOCK_UTMI_CLK>;
|
||||||
|
+ clock-names = "master", "sleep", "mock_utmi";
|
||||||
|
+ ranges;
|
||||||
|
+ status = "disabled";
|
||||||
|
+
|
||||||
|
+ dwc3@6000000 {
|
||||||
|
+ compatible = "snps,dwc3";
|
||||||
|
+ reg = <0x6000000 0xf8000>;
|
||||||
|
+ interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
+ phys = <&usb2_hs_phy>;
|
||||||
|
+ phy-names = "usb2-phy";
|
||||||
|
+ dr_mode = "host";
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,70 @@
|
||||||
|
From patchwork Mon May 21 20:57:38 2018
|
||||||
|
Content-Type: text/plain; charset="utf-8"
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Transfer-Encoding: 7bit
|
||||||
|
Subject: [v5,3/4] ARM: dts: qcom: add gpio-ranges property
|
||||||
|
X-Patchwork-Submitter: Christian Lamparter <chunkeey@gmail.com>
|
||||||
|
X-Patchwork-Id: 917856
|
||||||
|
Message-Id: <0ae3376606a89bcdf3fe753a5c967f7103699e09.1526935804.git.chunkeey@gmail.com>
|
||||||
|
To: linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
|
||||||
|
linux-arm-msm@vger.kernel.org, devicetree@vger.kernel.org
|
||||||
|
Cc: Bjorn Andersson <bjorn.andersson@linaro.org>,
|
||||||
|
Linus Walleij <linus.walleij@linaro.org>,
|
||||||
|
Stephen Boyd <sboyd@kernel.org>, David Brown <david.brown@linaro.org>,
|
||||||
|
Rob Herring <robh+dt@kernel.org>, Mark Rutland <mark.rutland@arm.com>,
|
||||||
|
Andy Gross <andy.gross@linaro.org>,
|
||||||
|
Sven Eckelmann <sven.eckelmann@openmesh.com>
|
||||||
|
Date: Mon, 21 May 2018 22:57:38 +0200
|
||||||
|
From: Christian Lamparter <chunkeey@gmail.com>
|
||||||
|
List-Id: <linux-gpio.vger.kernel.org>
|
||||||
|
|
||||||
|
This patch adds the gpio-ranges property to almost all of
|
||||||
|
the Qualcomm ARM platforms that utilize the pinctrl-msm
|
||||||
|
framework.
|
||||||
|
|
||||||
|
The gpio-ranges property is part of the gpiolib subsystem.
|
||||||
|
As a result, the binding text is available in section
|
||||||
|
"2.1 gpio- and pin-controller interaction" of
|
||||||
|
Documentation/devicetree/bindings/gpio/gpio.txt
|
||||||
|
|
||||||
|
For more information please see the patch titled:
|
||||||
|
"pinctrl: msm: fix gpio-hog related boot issues" from
|
||||||
|
this series.
|
||||||
|
|
||||||
|
Reported-by: Sven Eckelmann <sven.eckelmann@openmesh.com>
|
||||||
|
Tested-by: Sven Eckelmann <sven.eckelmann@openmesh.com> [ipq4019]
|
||||||
|
Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>
|
||||||
|
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
|
||||||
|
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
|
||||||
|
---
|
||||||
|
To help with git bisect, the DT update patch has been intentionally
|
||||||
|
placed after the "pinctrl: msm: fix gpio-hog related boot issues".
|
||||||
|
Otherwise - if the order was reveresed - and bisect decides to split
|
||||||
|
between these two patches, the gpiochip_add_pin_ranges() function
|
||||||
|
will be executed twice with the same parameters for the same pinctrl.
|
||||||
|
---
|
||||||
|
arch/arm/boot/dts/qcom-apq8064.dtsi | 1 +
|
||||||
|
arch/arm/boot/dts/qcom-apq8084.dtsi | 1 +
|
||||||
|
arch/arm/boot/dts/qcom-ipq4019.dtsi | 1 +
|
||||||
|
arch/arm/boot/dts/qcom-ipq8064.dtsi | 1 +
|
||||||
|
arch/arm/boot/dts/qcom-mdm9615.dtsi | 1 +
|
||||||
|
arch/arm/boot/dts/qcom-msm8660.dtsi | 1 +
|
||||||
|
arch/arm/boot/dts/qcom-msm8960.dtsi | 1 +
|
||||||
|
arch/arm/boot/dts/qcom-msm8974.dtsi | 1 +
|
||||||
|
arch/arm64/boot/dts/qcom/ipq8074.dtsi | 3 ++-
|
||||||
|
arch/arm64/boot/dts/qcom/msm8916.dtsi | 1 +
|
||||||
|
arch/arm64/boot/dts/qcom/msm8992.dtsi | 1 +
|
||||||
|
arch/arm64/boot/dts/qcom/msm8994.dtsi | 1 +
|
||||||
|
arch/arm64/boot/dts/qcom/msm8996.dtsi | 1 +
|
||||||
|
13 files changed, 14 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi
|
||||||
|
+++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi
|
||||||
|
@@ -201,6 +201,7 @@
|
||||||
|
compatible = "qcom,ipq4019-pinctrl";
|
||||||
|
reg = <0x01000000 0x300000>;
|
||||||
|
gpio-controller;
|
||||||
|
+ gpio-ranges = <&tlmm 0 0 100>;
|
||||||
|
#gpio-cells = <2>;
|
||||||
|
interrupt-controller;
|
||||||
|
#interrupt-cells = <2>;
|
|
@ -0,0 +1,115 @@
|
||||||
|
From f2b87dc1028b710ec8ce25808b9d21f92b376184 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Lamparter <chunkeey@googlemail.com>
|
||||||
|
Date: Sun, 11 Mar 2018 14:41:31 +0100
|
||||||
|
Subject: [PATCH 2/2] clk: fix apss cpu overclocking
|
||||||
|
|
||||||
|
There's an interaction issue between the clk changes:"
|
||||||
|
clk: qcom: ipq4019: Add the apss cpu pll divider clock node
|
||||||
|
clk: qcom: ipq4019: remove fixed clocks and add pll clocks
|
||||||
|
" and the cpufreq-dt.
|
||||||
|
|
||||||
|
cpufreq-dt is now spamming the kernel-log with the following:
|
||||||
|
|
||||||
|
[ 1099.190658] cpu cpu0: dev_pm_opp_set_rate: failed to find current OPP
|
||||||
|
for freq 761142857 (-34)
|
||||||
|
|
||||||
|
This only happens on certain devices like the Compex WPJ428
|
||||||
|
and AVM FritzBox!4040. However, other devices like the Asus
|
||||||
|
RT-AC58U and Meraki MR33 work just fine.
|
||||||
|
|
||||||
|
The issue stem from the fact that all higher CPU-Clocks
|
||||||
|
are achieved by switching the clock-parent to the P_DDRPLLAPSS
|
||||||
|
(ddrpllapss). Which is set by Qualcomm's proprietary bootcode
|
||||||
|
as part of the DDR calibration.
|
||||||
|
|
||||||
|
For example, the FB4040 uses 256 MiB Nanya NT5CC128M16IP clocked
|
||||||
|
at round 533 MHz (ddrpllsdcc = 190285714 Hz).
|
||||||
|
|
||||||
|
whereas the 128 MiB Nanya NT5CC64M16GP-DI in the ASUS RT-AC58U is
|
||||||
|
clocked at a slightly higher 537 MHz ( ddrpllsdcc = 192000000 Hz).
|
||||||
|
|
||||||
|
This patch attempts to fix the issue by modifying
|
||||||
|
clk_cpu_div_round_rate(), clk_cpu_div_set_rate(), clk_cpu_div_recalc_rate()
|
||||||
|
to use a new qcom_find_freq_close() function, which returns the closest
|
||||||
|
matching frequency, instead of the next higher. This way, the SoC in
|
||||||
|
the FB4040 (with its max clock speed of 710.4 MHz) will no longer
|
||||||
|
try to overclock to 761 MHz.
|
||||||
|
|
||||||
|
Fixes: d83dcacea18 ("clk: qcom: ipq4019: Add the apss cpu pll divider clock node")
|
||||||
|
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
|
||||||
|
Signed-off-by: John Crispin <john@phrozen.org>
|
||||||
|
---
|
||||||
|
drivers/clk/qcom/gcc-ipq4019.c | 34 +++++++++++++++++++++++++++++++---
|
||||||
|
1 file changed, 31 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
--- a/drivers/clk/qcom/gcc-ipq4019.c
|
||||||
|
+++ b/drivers/clk/qcom/gcc-ipq4019.c
|
||||||
|
@@ -1243,6 +1243,29 @@ static const struct clk_fepll_vco gcc_fe
|
||||||
|
.reg = 0x2f020,
|
||||||
|
};
|
||||||
|
|
||||||
|
+
|
||||||
|
+const struct freq_tbl *qcom_find_freq_close(const struct freq_tbl *f,
|
||||||
|
+ unsigned long rate)
|
||||||
|
+{
|
||||||
|
+ const struct freq_tbl *last = NULL;
|
||||||
|
+
|
||||||
|
+ for ( ; f->freq; f++) {
|
||||||
|
+ if (rate == f->freq)
|
||||||
|
+ return f;
|
||||||
|
+
|
||||||
|
+ if (f->freq > rate) {
|
||||||
|
+ if (!last ||
|
||||||
|
+ (f->freq - rate) < (rate - last->freq))
|
||||||
|
+ return f;
|
||||||
|
+ else
|
||||||
|
+ return last;
|
||||||
|
+ }
|
||||||
|
+ last = f;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return last;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Round rate function for APSS CPU PLL Clock divider.
|
||||||
|
* It looks up the frequency table and returns the next higher frequency
|
||||||
|
@@ -1255,7 +1278,7 @@ static long clk_cpu_div_round_rate(struc
|
||||||
|
struct clk_hw *p_hw;
|
||||||
|
const struct freq_tbl *f;
|
||||||
|
|
||||||
|
- f = qcom_find_freq(pll->freq_tbl, rate);
|
||||||
|
+ f = qcom_find_freq_close(pll->freq_tbl, rate);
|
||||||
|
if (!f)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
@@ -1278,7 +1301,7 @@ static int clk_cpu_div_set_rate(struct c
|
||||||
|
u32 mask;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
- f = qcom_find_freq(pll->freq_tbl, rate);
|
||||||
|
+ f = qcom_find_freq_close(pll->freq_tbl, rate);
|
||||||
|
if (!f)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
@@ -1305,6 +1328,7 @@ static unsigned long
|
||||||
|
clk_cpu_div_recalc_rate(struct clk_hw *hw,
|
||||||
|
unsigned long parent_rate)
|
||||||
|
{
|
||||||
|
+ const struct freq_tbl *f;
|
||||||
|
struct clk_fepll *pll = to_clk_fepll(hw);
|
||||||
|
u32 cdiv, pre_div;
|
||||||
|
u64 rate;
|
||||||
|
@@ -1325,7 +1349,11 @@ clk_cpu_div_recalc_rate(struct clk_hw *h
|
||||||
|
rate = clk_fepll_vco_calc_rate(pll, parent_rate) * 2;
|
||||||
|
do_div(rate, pre_div);
|
||||||
|
|
||||||
|
- return rate;
|
||||||
|
+ f = qcom_find_freq_close(pll->freq_tbl, rate);
|
||||||
|
+ if (!f)
|
||||||
|
+ return rate;
|
||||||
|
+
|
||||||
|
+ return f->freq;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct clk_ops clk_regmap_cpu_div_ops = {
|
|
@ -0,0 +1,29 @@
|
||||||
|
From 09f145f417a5d64d6b8d4476699dfb0eccc6c784 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Abhishek Sahu <absahu@codeaurora.org>
|
||||||
|
Date: Tue, 7 May 2019 10:14:05 +0300
|
||||||
|
Subject: [PATCH] ipq40xx: fix high resolution timer
|
||||||
|
|
||||||
|
Cherry-picked from CAF QSDK repo.
|
||||||
|
Original commit message:
|
||||||
|
The kernel is failing in switching the timer for high resolution
|
||||||
|
mode and clock source operates in 10ms resolution. The always-on
|
||||||
|
property needs to be given for timer device tree node to make
|
||||||
|
clock source working in 1ns resolution.
|
||||||
|
|
||||||
|
Change-Id: I7c00b3c74d97c2a30ac9f05e18b511a0550fd459
|
||||||
|
Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
|
||||||
|
Signed-off-by: Pavel Kubelun <be.dissent@gmail.com>
|
||||||
|
---
|
||||||
|
arch/arm/boot/dts/qcom-ipq4019.dtsi | 1 +
|
||||||
|
1 file changed, 1 insertion(+)
|
||||||
|
|
||||||
|
--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi
|
||||||
|
+++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi
|
||||||
|
@@ -166,6 +166,7 @@
|
||||||
|
<1 4 0xf08>,
|
||||||
|
<1 1 0xf08>;
|
||||||
|
clock-frequency = <48000000>;
|
||||||
|
+ always-on;
|
||||||
|
};
|
||||||
|
|
||||||
|
soc {
|
|
@ -0,0 +1,153 @@
|
||||||
|
From 97043d292365ae39d62b54a6d79dff98d048b501 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Robert Marko <robert.marko@sartura.hr>
|
||||||
|
Date: Wed, 22 Jan 2020 12:44:14 +0100
|
||||||
|
Subject: [PATCH] From ebf652b408200504194be32ad0a3f5bb49d6000a Mon Sep 17
|
||||||
|
00:00:00 2001 From: Robert Marko <robert.marko@sartura.hr> Date: Sun, 12 Jan
|
||||||
|
2020 12:30:01 +0100 Subject: [PATCH] regulator: add IPQ4019 SDHCI VQMMC LDO
|
||||||
|
driver
|
||||||
|
|
||||||
|
This introduces the IPQ4019 VQMMC LDO driver needed for
|
||||||
|
the SD/EMMC driver I/O level operation.
|
||||||
|
This will enable introducing SD/EMMC support for the built-in controller.
|
||||||
|
|
||||||
|
Signed-off-by: Mantas Pucka <mantas@8devices.com>
|
||||||
|
Signed-off-by: Robert Marko <robert.marko@sartura.hr>
|
||||||
|
Link: https://lore.kernel.org/r/20200112113003.11110-1-robert.marko@sartura.hr
|
||||||
|
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||||
|
---
|
||||||
|
drivers/regulator/Kconfig | 7 ++
|
||||||
|
drivers/regulator/Makefile | 1 +
|
||||||
|
drivers/regulator/vqmmc-ipq4019-regulator.c | 101 ++++++++++++++++++++
|
||||||
|
3 files changed, 109 insertions(+)
|
||||||
|
create mode 100644 drivers/regulator/vqmmc-ipq4019-regulator.c
|
||||||
|
|
||||||
|
--- a/drivers/regulator/Kconfig
|
||||||
|
+++ b/drivers/regulator/Kconfig
|
||||||
|
@@ -1077,6 +1077,13 @@ config REGULATOR_VEXPRESS
|
||||||
|
This driver provides support for voltage regulators available
|
||||||
|
on the ARM Ltd's Versatile Express platform.
|
||||||
|
|
||||||
|
+config REGULATOR_VQMMC_IPQ4019
|
||||||
|
+ tristate "IPQ4019 VQMMC SD LDO regulator support"
|
||||||
|
+ depends on ARCH_QCOM
|
||||||
|
+ help
|
||||||
|
+ This driver provides support for the VQMMC LDO I/0
|
||||||
|
+ voltage regulator of the IPQ4019 SD/EMMC controller.
|
||||||
|
+
|
||||||
|
config REGULATOR_WM831X
|
||||||
|
tristate "Wolfson Microelectronics WM831x PMIC regulators"
|
||||||
|
depends on MFD_WM831X
|
||||||
|
--- a/drivers/regulator/Makefile
|
||||||
|
+++ b/drivers/regulator/Makefile
|
||||||
|
@@ -132,6 +132,7 @@ obj-$(CONFIG_REGULATOR_TWL4030) += twl-r
|
||||||
|
obj-$(CONFIG_REGULATOR_UNIPHIER) += uniphier-regulator.o
|
||||||
|
obj-$(CONFIG_REGULATOR_VCTRL) += vctrl-regulator.o
|
||||||
|
obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress-regulator.o
|
||||||
|
+obj-$(CONFIG_REGULATOR_VQMMC_IPQ4019) += vqmmc-ipq4019-regulator.o
|
||||||
|
obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o
|
||||||
|
obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o
|
||||||
|
obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/drivers/regulator/vqmmc-ipq4019-regulator.c
|
||||||
|
@@ -0,0 +1,101 @@
|
||||||
|
+// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
+//
|
||||||
|
+// Copyright (c) 2019 Mantas Pucka <mantas@8devices.com>
|
||||||
|
+// Copyright (c) 2019 Robert Marko <robert.marko@sartura.hr>
|
||||||
|
+//
|
||||||
|
+// Driver for IPQ4019 SD/MMC controller's I/O LDO voltage regulator
|
||||||
|
+
|
||||||
|
+#include <linux/io.h>
|
||||||
|
+#include <linux/module.h>
|
||||||
|
+#include <linux/of.h>
|
||||||
|
+#include <linux/platform_device.h>
|
||||||
|
+#include <linux/regmap.h>
|
||||||
|
+#include <linux/regulator/driver.h>
|
||||||
|
+#include <linux/regulator/machine.h>
|
||||||
|
+#include <linux/regulator/of_regulator.h>
|
||||||
|
+
|
||||||
|
+static const unsigned int ipq4019_vmmc_voltages[] = {
|
||||||
|
+ 1500000, 1800000, 2500000, 3000000,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static const struct regulator_ops ipq4019_regulator_voltage_ops = {
|
||||||
|
+ .list_voltage = regulator_list_voltage_table,
|
||||||
|
+ .map_voltage = regulator_map_voltage_ascend,
|
||||||
|
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||||
|
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static const struct regulator_desc vmmc_regulator = {
|
||||||
|
+ .name = "vmmcq",
|
||||||
|
+ .ops = &ipq4019_regulator_voltage_ops,
|
||||||
|
+ .type = REGULATOR_VOLTAGE,
|
||||||
|
+ .owner = THIS_MODULE,
|
||||||
|
+ .volt_table = ipq4019_vmmc_voltages,
|
||||||
|
+ .n_voltages = ARRAY_SIZE(ipq4019_vmmc_voltages),
|
||||||
|
+ .vsel_reg = 0,
|
||||||
|
+ .vsel_mask = 0x3,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static const struct regmap_config ipq4019_vmmcq_regmap_config = {
|
||||||
|
+ .reg_bits = 32,
|
||||||
|
+ .reg_stride = 4,
|
||||||
|
+ .val_bits = 32,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int ipq4019_regulator_probe(struct platform_device *pdev)
|
||||||
|
+{
|
||||||
|
+ struct device *dev = &pdev->dev;
|
||||||
|
+ struct regulator_init_data *init_data;
|
||||||
|
+ struct regulator_config cfg = {};
|
||||||
|
+ struct regulator_dev *rdev;
|
||||||
|
+ struct resource *res;
|
||||||
|
+ struct regmap *rmap;
|
||||||
|
+ void __iomem *base;
|
||||||
|
+
|
||||||
|
+ init_data = of_get_regulator_init_data(dev, dev->of_node,
|
||||||
|
+ &vmmc_regulator);
|
||||||
|
+ if (!init_data)
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
+ base = devm_ioremap_resource(dev, res);
|
||||||
|
+ if (IS_ERR(base))
|
||||||
|
+ return PTR_ERR(base);
|
||||||
|
+
|
||||||
|
+ rmap = devm_regmap_init_mmio(dev, base, &ipq4019_vmmcq_regmap_config);
|
||||||
|
+ if (IS_ERR(rmap))
|
||||||
|
+ return PTR_ERR(rmap);
|
||||||
|
+
|
||||||
|
+ cfg.dev = dev;
|
||||||
|
+ cfg.init_data = init_data;
|
||||||
|
+ cfg.of_node = dev->of_node;
|
||||||
|
+ cfg.regmap = rmap;
|
||||||
|
+
|
||||||
|
+ rdev = devm_regulator_register(dev, &vmmc_regulator, &cfg);
|
||||||
|
+ if (IS_ERR(rdev)) {
|
||||||
|
+ dev_err(dev, "Failed to register regulator: %ld\n",
|
||||||
|
+ PTR_ERR(rdev));
|
||||||
|
+ return PTR_ERR(rdev);
|
||||||
|
+ }
|
||||||
|
+ platform_set_drvdata(pdev, rdev);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static const struct of_device_id regulator_ipq4019_of_match[] = {
|
||||||
|
+ { .compatible = "qcom,vqmmc-ipq4019-regulator", },
|
||||||
|
+ {},
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static struct platform_driver ipq4019_regulator_driver = {
|
||||||
|
+ .probe = ipq4019_regulator_probe,
|
||||||
|
+ .driver = {
|
||||||
|
+ .name = "vqmmc-ipq4019-regulator",
|
||||||
|
+ .of_match_table = of_match_ptr(regulator_ipq4019_of_match),
|
||||||
|
+ },
|
||||||
|
+};
|
||||||
|
+module_platform_driver(ipq4019_regulator_driver);
|
||||||
|
+
|
||||||
|
+MODULE_LICENSE("GPL");
|
||||||
|
+MODULE_AUTHOR("Mantas Pucka <mantas@8devices.com>");
|
||||||
|
+MODULE_DESCRIPTION("IPQ4019 VQMMC voltage regulator");
|
|
@ -0,0 +1,36 @@
|
||||||
|
From 04b3b72b5b8fdb883bfdc619cb29b03641b1cc6a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Robert Marko <robimarko@gmail.com>
|
||||||
|
Date: Thu, 15 Aug 2019 19:28:23 +0200
|
||||||
|
Subject: [PATCH] ARM: dts: qcom: ipq4019: Add SDHCI controller node
|
||||||
|
|
||||||
|
IPQ4019 has a built in SD/eMMC controller which is supported by the
|
||||||
|
SDHCI MSM driver, by the "qcom,sdhci-msm-v4" binding.
|
||||||
|
So lets add the appropriate node for it.
|
||||||
|
|
||||||
|
Signed-off-by: Robert Marko <robimarko@gmail.com>
|
||||||
|
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
|
||||||
|
---
|
||||||
|
arch/arm/boot/dts/qcom-ipq4019.dtsi | 12 ++++++++++++
|
||||||
|
1 file changed, 12 insertions(+)
|
||||||
|
|
||||||
|
--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi
|
||||||
|
+++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi
|
||||||
|
@@ -209,6 +209,18 @@
|
||||||
|
interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
};
|
||||||
|
|
||||||
|
+ sdhci: sdhci@7824900 {
|
||||||
|
+ compatible = "qcom,sdhci-msm-v4";
|
||||||
|
+ reg = <0x7824900 0x11c>, <0x7824000 0x800>;
|
||||||
|
+ interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
+ interrupt-names = "hc_irq", "pwr_irq";
|
||||||
|
+ bus-width = <8>;
|
||||||
|
+ clocks = <&gcc GCC_SDCC1_APPS_CLK>, <&gcc GCC_SDCC1_AHB_CLK>,
|
||||||
|
+ <&gcc GCC_DCD_XO_CLK>;
|
||||||
|
+ clock-names = "core", "iface", "xo";
|
||||||
|
+ status = "disabled";
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
blsp_dma: dma@7884000 {
|
||||||
|
compatible = "qcom,bam-v1.7.0";
|
||||||
|
reg = <0x07884000 0x23000>;
|
|
@ -0,0 +1,32 @@
|
||||||
|
From 77d9b11ae7269dcf376c3b9493209f712524e986 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Robert Marko <robert.marko@sartura.hr>
|
||||||
|
Date: Wed, 22 Jan 2020 12:56:35 +0100
|
||||||
|
Subject: [PATCH] arm: dts: IPQ4019: add SDHCI VQMMC LDO node
|
||||||
|
|
||||||
|
Since we now have driver for the SDHCI VQMMC LDO needed
|
||||||
|
for I/0 voltage levels lets introduce the necessary node for it.
|
||||||
|
|
||||||
|
Signed-off-by: Robert Marko <robert.marko@sartura.hr>
|
||||||
|
---
|
||||||
|
arch/arm/boot/dts/qcom-ipq4019.dtsi | 10 ++++++++++
|
||||||
|
1 file changed, 10 insertions(+)
|
||||||
|
|
||||||
|
--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi
|
||||||
|
+++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi
|
||||||
|
@@ -209,6 +209,16 @@
|
||||||
|
interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
};
|
||||||
|
|
||||||
|
+ vqmmc: regulator@1948000 {
|
||||||
|
+ compatible = "qcom,vqmmc-ipq4019-regulator";
|
||||||
|
+ reg = <0x01948000 0x4>;
|
||||||
|
+ regulator-name = "vqmmc";
|
||||||
|
+ regulator-min-microvolt = <1500000>;
|
||||||
|
+ regulator-max-microvolt = <3000000>;
|
||||||
|
+ regulator-always-on;
|
||||||
|
+ status = "disabled";
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
sdhci: sdhci@7824900 {
|
||||||
|
compatible = "qcom,sdhci-msm-v4";
|
||||||
|
reg = <0x7824900 0x11c>, <0x7824000 0x800>;
|
|
@ -0,0 +1,52 @@
|
||||||
|
From 480c1f7648fc586db12d6003c717c23667a4fcf0 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ram Chandra Jangir <rjangir@codeaurora.org>
|
||||||
|
Date: Tue, 28 Mar 2017 22:35:33 +0530
|
||||||
|
Subject: [PATCH] clk: qcom: ipq4019: add ess reset
|
||||||
|
|
||||||
|
Added the ESS reset in IPQ4019 GCC.
|
||||||
|
|
||||||
|
Signed-off-by: Ram Chandra Jangir <rjangir@codeaurora.org>
|
||||||
|
---
|
||||||
|
drivers/clk/qcom/gcc-ipq4019.c | 11 +++++++++++
|
||||||
|
include/dt-bindings/clock/qcom,gcc-ipq4019.h | 11 +++++++++++
|
||||||
|
2 files changed, 22 insertions(+)
|
||||||
|
|
||||||
|
--- a/drivers/clk/qcom/gcc-ipq4019.c
|
||||||
|
+++ b/drivers/clk/qcom/gcc-ipq4019.c
|
||||||
|
@@ -1736,6 +1736,17 @@ static const struct qcom_reset_map gcc_i
|
||||||
|
[GCC_TCSR_BCR] = {0x22000, 0},
|
||||||
|
[GCC_MPM_BCR] = {0x24000, 0},
|
||||||
|
[GCC_SPDM_BCR] = {0x25000, 0},
|
||||||
|
+ [ESS_MAC1_ARES] = {0x1200C, 0},
|
||||||
|
+ [ESS_MAC2_ARES] = {0x1200C, 1},
|
||||||
|
+ [ESS_MAC3_ARES] = {0x1200C, 2},
|
||||||
|
+ [ESS_MAC4_ARES] = {0x1200C, 3},
|
||||||
|
+ [ESS_MAC5_ARES] = {0x1200C, 4},
|
||||||
|
+ [ESS_PSGMII_ARES] = {0x1200C, 5},
|
||||||
|
+ [ESS_MAC1_CLK_DIS] = {0x1200C, 8},
|
||||||
|
+ [ESS_MAC2_CLK_DIS] = {0x1200C, 9},
|
||||||
|
+ [ESS_MAC3_CLK_DIS] = {0x1200C, 10},
|
||||||
|
+ [ESS_MAC4_CLK_DIS] = {0x1200C, 11},
|
||||||
|
+ [ESS_MAC5_CLK_DIS] = {0x1200C, 12},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct regmap_config gcc_ipq4019_regmap_config = {
|
||||||
|
--- a/include/dt-bindings/clock/qcom,gcc-ipq4019.h
|
||||||
|
+++ b/include/dt-bindings/clock/qcom,gcc-ipq4019.h
|
||||||
|
@@ -165,5 +165,16 @@
|
||||||
|
#define GCC_QDSS_BCR 69
|
||||||
|
#define GCC_MPM_BCR 70
|
||||||
|
#define GCC_SPDM_BCR 71
|
||||||
|
+#define ESS_MAC1_ARES 72
|
||||||
|
+#define ESS_MAC2_ARES 73
|
||||||
|
+#define ESS_MAC3_ARES 74
|
||||||
|
+#define ESS_MAC4_ARES 75
|
||||||
|
+#define ESS_MAC5_ARES 76
|
||||||
|
+#define ESS_PSGMII_ARES 77
|
||||||
|
+#define ESS_MAC1_CLK_DIS 78
|
||||||
|
+#define ESS_MAC2_CLK_DIS 79
|
||||||
|
+#define ESS_MAC3_CLK_DIS 80
|
||||||
|
+#define ESS_MAC4_CLK_DIS 81
|
||||||
|
+#define ESS_MAC5_CLK_DIS 82
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,26 @@
|
||||||
|
From 158acdbf0336f601971637f988b57a6a67a0869b Mon Sep 17 00:00:00 2001
|
||||||
|
From: David Bauer <mail@david-bauer.net>
|
||||||
|
Date: Sun, 15 Dec 2019 13:10:50 +0100
|
||||||
|
Subject: [PATCH] mtd: spi-nor: Add support for mx25r3235f
|
||||||
|
|
||||||
|
Add MTD support for the Macronix MX25R3235F SPI NOR chip from Macronix.
|
||||||
|
The chip has 4MB of total capacity, divided into a total of 64 sectors,
|
||||||
|
each 64KB sized. The chip also supports 4KB large sectors.
|
||||||
|
Additionally, it supports dual and quad read modes.
|
||||||
|
|
||||||
|
Signed-off-by: David Bauer <mail@david-bauer.net>
|
||||||
|
---
|
||||||
|
drivers/mtd/spi-nor/spi-nor.c | 2 ++
|
||||||
|
1 file changed, 2 insertions(+)
|
||||||
|
|
||||||
|
--- a/drivers/mtd/spi-nor/spi-nor.c
|
||||||
|
+++ b/drivers/mtd/spi-nor/spi-nor.c
|
||||||
|
@@ -2344,6 +2344,8 @@ static const struct flash_info spi_nor_i
|
||||||
|
{ "mx25u6435f", INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) },
|
||||||
|
{ "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
|
||||||
|
{ "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
|
||||||
|
+ { "mx25r3235f", INFO(0xc22816, 0, 64 * 1024, 64,
|
||||||
|
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
|
||||||
|
{ "mx25u12835f", INFO(0xc22538, 0, 64 * 1024, 256,
|
||||||
|
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
|
||||||
|
{ "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512,
|
|
@ -0,0 +1,25 @@
|
||||||
|
From 0e28623a11f3916c1fe5b7e789c7ab8ca932a929 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Robert Marko <robimarko@gmail.com>
|
||||||
|
Date: Wed, 22 Jan 2020 13:02:13 +0100
|
||||||
|
Subject: [PATCH] mmc: sdhci: sdhci-msm: use sdhci_set_clock instead of
|
||||||
|
sdhci_msm_set_clock
|
||||||
|
|
||||||
|
When using sdhci_msm_set_clock clock setting will fail, so lets
|
||||||
|
use the generic sdhci_set_clock.
|
||||||
|
|
||||||
|
Signed-off-by: Robert Marko <robimarko@gmail.com>
|
||||||
|
---
|
||||||
|
drivers/mmc/host/sdhci-msm.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
--- a/drivers/mmc/host/sdhci-msm.c
|
||||||
|
+++ b/drivers/mmc/host/sdhci-msm.c
|
||||||
|
@@ -1746,7 +1746,7 @@ MODULE_DEVICE_TABLE(of, sdhci_msm_dt_mat
|
||||||
|
|
||||||
|
static const struct sdhci_ops sdhci_msm_ops = {
|
||||||
|
.reset = sdhci_reset,
|
||||||
|
- .set_clock = sdhci_msm_set_clock,
|
||||||
|
+ .set_clock = sdhci_set_clock,
|
||||||
|
.get_min_clock = sdhci_msm_get_min_clock,
|
||||||
|
.get_max_clock = sdhci_msm_get_max_clock,
|
||||||
|
.set_bus_width = sdhci_set_bus_width,
|
|
@ -0,0 +1,225 @@
|
||||||
|
--- a/drivers/net/phy/Kconfig
|
||||||
|
+++ b/drivers/net/phy/Kconfig
|
||||||
|
@@ -580,6 +580,13 @@ config XILINX_GMII2RGMII
|
||||||
|
the Reduced Gigabit Media Independent Interface(RGMII) between
|
||||||
|
Ethernet physical media devices and the Gigabit Ethernet controller.
|
||||||
|
|
||||||
|
+config MDIO_IPQ40XX
|
||||||
|
+ tristate "Qualcomm Atheros ipq40xx MDIO interface"
|
||||||
|
+ depends on HAS_IOMEM && OF
|
||||||
|
+ ---help---
|
||||||
|
+ This driver supports the MDIO interface found in Qualcomm
|
||||||
|
+ Atheros ipq40xx Soc chip.
|
||||||
|
+
|
||||||
|
endif # PHYLIB
|
||||||
|
|
||||||
|
config MICREL_KS8995MA
|
||||||
|
--- a/drivers/net/phy/Makefile
|
||||||
|
+++ b/drivers/net/phy/Makefile
|
||||||
|
@@ -51,6 +51,7 @@ obj-$(CONFIG_MDIO_CAVIUM) += mdio-cavium
|
||||||
|
obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o
|
||||||
|
obj-$(CONFIG_MDIO_HISI_FEMAC) += mdio-hisi-femac.o
|
||||||
|
obj-$(CONFIG_MDIO_I2C) += mdio-i2c.o
|
||||||
|
+obj-$(CONFIG_MDIO_IPQ40XX) += mdio-ipq40xx.o
|
||||||
|
obj-$(CONFIG_MDIO_MOXART) += mdio-moxart.o
|
||||||
|
obj-$(CONFIG_MDIO_MSCC_MIIM) += mdio-mscc-miim.o
|
||||||
|
obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/drivers/net/phy/mdio-ipq40xx.c
|
||||||
|
@@ -0,0 +1,196 @@
|
||||||
|
+/*
|
||||||
|
+ * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
|
||||||
|
+ *
|
||||||
|
+ * Permission to use, copy, modify, and/or distribute this software for
|
||||||
|
+ * any purpose with or without fee is hereby granted, provided that the
|
||||||
|
+ * above copyright notice and this permission notice appear in all copies.
|
||||||
|
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||||
|
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include <linux/delay.h>
|
||||||
|
+#include <linux/kernel.h>
|
||||||
|
+#include <linux/module.h>
|
||||||
|
+#include <linux/mutex.h>
|
||||||
|
+#include <linux/io.h>
|
||||||
|
+#include <linux/of_address.h>
|
||||||
|
+#include <linux/of_mdio.h>
|
||||||
|
+#include <linux/phy.h>
|
||||||
|
+#include <linux/platform_device.h>
|
||||||
|
+
|
||||||
|
+#define MDIO_CTRL_0_REG 0x40
|
||||||
|
+#define MDIO_CTRL_1_REG 0x44
|
||||||
|
+#define MDIO_CTRL_2_REG 0x48
|
||||||
|
+#define MDIO_CTRL_3_REG 0x4c
|
||||||
|
+#define MDIO_CTRL_4_REG 0x50
|
||||||
|
+#define MDIO_CTRL_4_ACCESS_BUSY BIT(16)
|
||||||
|
+#define MDIO_CTRL_4_ACCESS_START BIT(8)
|
||||||
|
+#define MDIO_CTRL_4_ACCESS_CODE_READ 0
|
||||||
|
+#define MDIO_CTRL_4_ACCESS_CODE_WRITE 1
|
||||||
|
+#define CTRL_0_REG_DEFAULT_VALUE 0x150FF
|
||||||
|
+
|
||||||
|
+#define IPQ40XX_MDIO_RETRY 1000
|
||||||
|
+#define IPQ40XX_MDIO_DELAY 10
|
||||||
|
+
|
||||||
|
+struct ipq40xx_mdio_data {
|
||||||
|
+ struct mii_bus *mii_bus;
|
||||||
|
+ void __iomem *membase;
|
||||||
|
+ struct device *dev;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int ipq40xx_mdio_wait_busy(struct ipq40xx_mdio_data *am)
|
||||||
|
+{
|
||||||
|
+ int i;
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < IPQ40XX_MDIO_RETRY; i++) {
|
||||||
|
+ unsigned int busy;
|
||||||
|
+
|
||||||
|
+ busy = readl(am->membase + MDIO_CTRL_4_REG) &
|
||||||
|
+ MDIO_CTRL_4_ACCESS_BUSY;
|
||||||
|
+ if (!busy)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ /* BUSY might take to be cleard by 15~20 times of loop */
|
||||||
|
+ udelay(IPQ40XX_MDIO_DELAY);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ dev_err(am->dev, "%s: MDIO operation timed out\n", am->mii_bus->name);
|
||||||
|
+
|
||||||
|
+ return -ETIMEDOUT;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int ipq40xx_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
|
||||||
|
+{
|
||||||
|
+ struct ipq40xx_mdio_data *am = bus->priv;
|
||||||
|
+ int value = 0;
|
||||||
|
+ unsigned int cmd = 0;
|
||||||
|
+
|
||||||
|
+ lockdep_assert_held(&bus->mdio_lock);
|
||||||
|
+
|
||||||
|
+ if (ipq40xx_mdio_wait_busy(am))
|
||||||
|
+ return -ETIMEDOUT;
|
||||||
|
+
|
||||||
|
+ /* issue the phy address and reg */
|
||||||
|
+ writel((mii_id << 8) | regnum, am->membase + MDIO_CTRL_1_REG);
|
||||||
|
+
|
||||||
|
+ cmd = MDIO_CTRL_4_ACCESS_START|MDIO_CTRL_4_ACCESS_CODE_READ;
|
||||||
|
+
|
||||||
|
+ /* issue read command */
|
||||||
|
+ writel(cmd, am->membase + MDIO_CTRL_4_REG);
|
||||||
|
+
|
||||||
|
+ /* Wait read complete */
|
||||||
|
+ if (ipq40xx_mdio_wait_busy(am))
|
||||||
|
+ return -ETIMEDOUT;
|
||||||
|
+
|
||||||
|
+ /* Read data */
|
||||||
|
+ value = readl(am->membase + MDIO_CTRL_3_REG);
|
||||||
|
+
|
||||||
|
+ return value;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int ipq40xx_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
|
||||||
|
+ u16 value)
|
||||||
|
+{
|
||||||
|
+ struct ipq40xx_mdio_data *am = bus->priv;
|
||||||
|
+ unsigned int cmd = 0;
|
||||||
|
+
|
||||||
|
+ lockdep_assert_held(&bus->mdio_lock);
|
||||||
|
+
|
||||||
|
+ if (ipq40xx_mdio_wait_busy(am))
|
||||||
|
+ return -ETIMEDOUT;
|
||||||
|
+
|
||||||
|
+ /* issue the phy address and reg */
|
||||||
|
+ writel((mii_id << 8) | regnum, am->membase + MDIO_CTRL_1_REG);
|
||||||
|
+
|
||||||
|
+ /* issue write data */
|
||||||
|
+ writel(value, am->membase + MDIO_CTRL_2_REG);
|
||||||
|
+
|
||||||
|
+ cmd = MDIO_CTRL_4_ACCESS_START|MDIO_CTRL_4_ACCESS_CODE_WRITE;
|
||||||
|
+ /* issue write command */
|
||||||
|
+ writel(cmd, am->membase + MDIO_CTRL_4_REG);
|
||||||
|
+
|
||||||
|
+ /* Wait write complete */
|
||||||
|
+ if (ipq40xx_mdio_wait_busy(am))
|
||||||
|
+ return -ETIMEDOUT;
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int ipq40xx_mdio_probe(struct platform_device *pdev)
|
||||||
|
+{
|
||||||
|
+ struct ipq40xx_mdio_data *am;
|
||||||
|
+ struct resource *res;
|
||||||
|
+ int i;
|
||||||
|
+
|
||||||
|
+ am = devm_kzalloc(&pdev->dev, sizeof(*am), GFP_KERNEL);
|
||||||
|
+ if (!am)
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+
|
||||||
|
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
+ if (!res) {
|
||||||
|
+ dev_err(&pdev->dev, "no iomem resource found\n");
|
||||||
|
+ return -ENXIO;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ am->membase = devm_ioremap_resource(&pdev->dev, res);
|
||||||
|
+ if (IS_ERR(am->membase)) {
|
||||||
|
+ dev_err(&pdev->dev, "unable to ioremap registers\n");
|
||||||
|
+ return PTR_ERR(am->membase);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ am->mii_bus = devm_mdiobus_alloc(&pdev->dev);
|
||||||
|
+ if (!am->mii_bus)
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+
|
||||||
|
+ writel(CTRL_0_REG_DEFAULT_VALUE, am->membase + MDIO_CTRL_0_REG);
|
||||||
|
+
|
||||||
|
+ am->mii_bus->name = "ipq40xx_mdio";
|
||||||
|
+ am->mii_bus->read = ipq40xx_mdio_read;
|
||||||
|
+ am->mii_bus->write = ipq40xx_mdio_write;
|
||||||
|
+ am->mii_bus->priv = am;
|
||||||
|
+ am->mii_bus->parent = &pdev->dev;
|
||||||
|
+ snprintf(am->mii_bus->id, MII_BUS_ID_SIZE, "%s", dev_name(&pdev->dev));
|
||||||
|
+
|
||||||
|
+ am->dev = &pdev->dev;
|
||||||
|
+ platform_set_drvdata(pdev, am);
|
||||||
|
+
|
||||||
|
+ return of_mdiobus_register(am->mii_bus, pdev->dev.of_node);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int ipq40xx_mdio_remove(struct platform_device *pdev)
|
||||||
|
+{
|
||||||
|
+ struct ipq40xx_mdio_data *am = platform_get_drvdata(pdev);
|
||||||
|
+
|
||||||
|
+ mdiobus_unregister(am->mii_bus);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static const struct of_device_id ipq40xx_mdio_dt_ids[] = {
|
||||||
|
+ { .compatible = "qcom,ipq4019-mdio" },
|
||||||
|
+ { }
|
||||||
|
+};
|
||||||
|
+MODULE_DEVICE_TABLE(of, ipq40xx_mdio_dt_ids);
|
||||||
|
+
|
||||||
|
+static struct platform_driver ipq40xx_mdio_driver = {
|
||||||
|
+ .probe = ipq40xx_mdio_probe,
|
||||||
|
+ .remove = ipq40xx_mdio_remove,
|
||||||
|
+ .driver = {
|
||||||
|
+ .name = "ipq40xx-mdio",
|
||||||
|
+ .of_match_table = ipq40xx_mdio_dt_ids,
|
||||||
|
+ },
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+module_platform_driver(ipq40xx_mdio_driver);
|
||||||
|
+
|
||||||
|
+#define DRV_VERSION "1.0"
|
||||||
|
+
|
||||||
|
+MODULE_DESCRIPTION("IPQ40XX MDIO interface driver");
|
||||||
|
+MODULE_AUTHOR("Qualcomm Atheros");
|
||||||
|
+MODULE_VERSION(DRV_VERSION);
|
||||||
|
+MODULE_LICENSE("Dual BSD/GPL");
|
|
@ -0,0 +1,52 @@
|
||||||
|
From 09ed737593f71bcca08a537a6c15264a1a6add08 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Lamparter <chunkeey@gmail.com>
|
||||||
|
Date: Sun, 20 Nov 2016 01:10:33 +0100
|
||||||
|
Subject: [PATCH] dts: ipq4019: add mdio node for ethernet
|
||||||
|
|
||||||
|
This patch adds the mdio device-tree node.
|
||||||
|
This is where the switch is connected to, so it's needed
|
||||||
|
for the ethernet interfaces.
|
||||||
|
|
||||||
|
Note: The driver isn't anywhere close to be upstream,
|
||||||
|
so the info might change.
|
||||||
|
---
|
||||||
|
arch/arm/boot/dts/qcom-ipq4019.dtsi | 28 ++++++++++++++++++++++++++++
|
||||||
|
1 file changed, 28 insertions(+)
|
||||||
|
|
||||||
|
--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi
|
||||||
|
+++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi
|
||||||
|
@@ -588,6 +588,34 @@
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
|
+ mdio: mdio@90000 {
|
||||||
|
+ #address-cells = <1>;
|
||||||
|
+ #size-cells = <0>;
|
||||||
|
+ compatible = "qcom,ipq4019-mdio";
|
||||||
|
+ reg = <0x90000 0x64>;
|
||||||
|
+ status = "disabled";
|
||||||
|
+
|
||||||
|
+ ethphy0: ethernet-phy@0 {
|
||||||
|
+ reg = <0>;
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ ethphy1: ethernet-phy@1 {
|
||||||
|
+ reg = <1>;
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ ethphy2: ethernet-phy@2 {
|
||||||
|
+ reg = <2>;
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ ethphy3: ethernet-phy@3 {
|
||||||
|
+ reg = <3>;
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ ethphy4: ethernet-phy@4 {
|
||||||
|
+ reg = <4>;
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
usb3_ss_phy: ssphy@9a000 {
|
||||||
|
compatible = "qcom,usb-ss-ipq4019-phy";
|
||||||
|
#phy-cells = <0>;
|
|
@ -0,0 +1,46 @@
|
||||||
|
From 9deeec35dd3b628b95624e41d4e04acf728991ba Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Lamparter <chunkeey@gmail.com>
|
||||||
|
Date: Sun, 20 Nov 2016 02:20:54 +0100
|
||||||
|
Subject: [PATCH] dts: ipq4019: add PHY/switch nodes
|
||||||
|
|
||||||
|
This patch adds both the "qcom,ess-switch" and "qcom,ess-psgmii"
|
||||||
|
nodes which are needed for the ar40xx.c driver to initialize the
|
||||||
|
switch.
|
||||||
|
|
||||||
|
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
|
||||||
|
---
|
||||||
|
arch/arm/boot/dts/qcom-ipq4019.dtsi | 23 +++++++++++++++++++++++
|
||||||
|
1 file changed, 23 insertions(+)
|
||||||
|
|
||||||
|
--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi
|
||||||
|
+++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi
|
||||||
|
@@ -616,6 +616,29 @@
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
+ ess-switch@c000000 {
|
||||||
|
+ compatible = "qcom,ess-switch";
|
||||||
|
+ reg = <0xc000000 0x80000>;
|
||||||
|
+ switch_access_mode = "local bus";
|
||||||
|
+ resets = <&gcc ESS_RESET>;
|
||||||
|
+ reset-names = "ess_rst";
|
||||||
|
+ clocks = <&gcc GCC_ESS_CLK>;
|
||||||
|
+ clock-names = "ess_clk";
|
||||||
|
+ switch_cpu_bmp = <0x1>;
|
||||||
|
+ switch_lan_bmp = <0x1e>;
|
||||||
|
+ switch_wan_bmp = <0x20>;
|
||||||
|
+ switch_mac_mode = <0>; /* PORT_WRAPPER_PSGMII */
|
||||||
|
+ switch_initvlas = <0x7c 0x54>;
|
||||||
|
+ status = "disabled";
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ ess-psgmii@98000 {
|
||||||
|
+ compatible = "qcom,ess-psgmii";
|
||||||
|
+ reg = <0x98000 0x800>;
|
||||||
|
+ psgmii_access_mode = "local bus";
|
||||||
|
+ status = "disabled";
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
usb3_ss_phy: ssphy@9a000 {
|
||||||
|
compatible = "qcom,usb-ss-ipq4019-phy";
|
||||||
|
#phy-cells = <0>;
|
|
@ -0,0 +1,53 @@
|
||||||
|
From 7c129254adb1093d10a62ed7bf7b956fcc6ffe34 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Rakesh Nair <ranair@codeaurora.org>
|
||||||
|
Date: Wed, 20 Jul 2016 15:02:01 +0530
|
||||||
|
Subject: [PATCH] net: IPQ4019 needs rfs/vlan_tag callbacks in
|
||||||
|
netdev_ops
|
||||||
|
|
||||||
|
Add callback support to get default vlan tag and register
|
||||||
|
receive flow steering filter.
|
||||||
|
|
||||||
|
Used by IPQ4019 ess-edma driver.
|
||||||
|
|
||||||
|
BUG=chrome-os-partner:33096
|
||||||
|
TEST=none
|
||||||
|
|
||||||
|
Change-Id: I266070e4a0fbe4a0d9966fe79a71e50ec4f26c75
|
||||||
|
Signed-off-by: Rakesh Nair <ranair@codeaurora.org>
|
||||||
|
Reviewed-on: https://chromium-review.googlesource.com/362203
|
||||||
|
Commit-Ready: Grant Grundler <grundler@chromium.org>
|
||||||
|
Tested-by: Grant Grundler <grundler@chromium.org>
|
||||||
|
Reviewed-by: Grant Grundler <grundler@chromium.org>
|
||||||
|
---
|
||||||
|
include/linux/netdevice.h | 13 +++++++++++++
|
||||||
|
1 file changed, 13 insertions(+)
|
||||||
|
|
||||||
|
--- a/include/linux/netdevice.h
|
||||||
|
+++ b/include/linux/netdevice.h
|
||||||
|
@@ -776,6 +776,16 @@ struct xps_map {
|
||||||
|
#define XPS_MIN_MAP_ALLOC ((L1_CACHE_ALIGN(offsetof(struct xps_map, queues[1])) \
|
||||||
|
- sizeof(struct xps_map)) / sizeof(u16))
|
||||||
|
|
||||||
|
+#ifdef CONFIG_RFS_ACCEL
|
||||||
|
+typedef int (*set_rfs_filter_callback_t)(struct net_device *dev,
|
||||||
|
+ __be32 src,
|
||||||
|
+ __be32 dst,
|
||||||
|
+ __be16 sport,
|
||||||
|
+ __be16 dport,
|
||||||
|
+ u8 proto,
|
||||||
|
+ u16 rxq_index,
|
||||||
|
+ u32 action);
|
||||||
|
+#endif
|
||||||
|
/*
|
||||||
|
* This structure holds all XPS maps for device. Maps are indexed by CPU.
|
||||||
|
*/
|
||||||
|
@@ -1379,6 +1389,9 @@ struct net_device_ops {
|
||||||
|
const struct sk_buff *skb,
|
||||||
|
u16 rxq_index,
|
||||||
|
u32 flow_id);
|
||||||
|
+ int (*ndo_register_rfs_filter)(struct net_device *dev,
|
||||||
|
+ set_rfs_filter_callback_t set_filter);
|
||||||
|
+ int (*ndo_get_default_vlan_tag)(struct net_device *net);
|
||||||
|
#endif
|
||||||
|
int (*ndo_add_slave)(struct net_device *dev,
|
||||||
|
struct net_device *slave_dev,
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,48 @@
|
||||||
|
From 12e9319da1adacac92930c899c99f0e1970cac11 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Lamparter <chunkeey@googlemail.com>
|
||||||
|
Date: Thu, 19 Jan 2017 02:01:31 +0100
|
||||||
|
Subject: [PATCH 33/38] NET: add qualcomm essedma ethernet driver
|
||||||
|
|
||||||
|
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
|
||||||
|
---
|
||||||
|
drivers/net/ethernet/qualcomm/Kconfig | 9 +++++++++
|
||||||
|
drivers/net/ethernet/qualcomm/Makefile | 1 +
|
||||||
|
2 files changed, 10 insertions(+)
|
||||||
|
|
||||||
|
--- a/drivers/net/ethernet/qualcomm/Kconfig
|
||||||
|
+++ b/drivers/net/ethernet/qualcomm/Kconfig
|
||||||
|
@@ -62,4 +62,13 @@ config QCOM_EMAC
|
||||||
|
|
||||||
|
source "drivers/net/ethernet/qualcomm/rmnet/Kconfig"
|
||||||
|
|
||||||
|
+config ESSEDMA
|
||||||
|
+ tristate "Qualcomm Atheros ESS Edma support"
|
||||||
|
+ ---help---
|
||||||
|
+ This driver supports ethernet edma adapter.
|
||||||
|
+ Say Y to build this driver.
|
||||||
|
+
|
||||||
|
+ To compile this driver as a module, choose M here. The module
|
||||||
|
+ will be called essedma.ko.
|
||||||
|
+
|
||||||
|
endif # NET_VENDOR_QUALCOMM
|
||||||
|
--- a/drivers/net/ethernet/qualcomm/Makefile
|
||||||
|
+++ b/drivers/net/ethernet/qualcomm/Makefile
|
||||||
|
@@ -10,5 +10,6 @@ obj-$(CONFIG_QCA7000_UART) += qcauart.o
|
||||||
|
qcauart-objs := qca_uart.o
|
||||||
|
|
||||||
|
obj-y += emac/
|
||||||
|
+obj-$(CONFIG_ESSEDMA) += essedma/
|
||||||
|
|
||||||
|
obj-$(CONFIG_RMNET) += rmnet/
|
||||||
|
|
||||||
|
--- a/drivers/net/ethernet/qualcomm/essedma/edma.c
|
||||||
|
+++ b/drivers/net/ethernet/qualcomm/essedma/edma.c
|
||||||
|
@@ -1493,7 +1493,7 @@
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if (skb->protocol == htons(ETH_P_IPV6)) {
|
||||||
|
- dev_err(&adapter->pdev->dev, "IPv6 not supported\n");
|
||||||
|
+
|
||||||
|
res = -EINVAL;
|
||||||
|
goto no_protocol_err;
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
From c611d3780fa101662a822d10acf8feb04ca97409 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Lamparter <chunkeey@gmail.com>
|
||||||
|
Date: Sun, 20 Nov 2016 01:01:10 +0100
|
||||||
|
Subject: [PATCH] dts: ipq4019: add ethernet essedma node
|
||||||
|
|
||||||
|
This patch adds the device-tree node for the ethernet
|
||||||
|
interfaces.
|
||||||
|
|
||||||
|
Note: The driver isn't anywhere close to be upstream,
|
||||||
|
so the info might change.
|
||||||
|
|
||||||
|
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
|
||||||
|
---
|
||||||
|
arch/arm/boot/dts/qcom-ipq4019.dtsi | 60 +++++++++++++++++++++++++++++++++++++
|
||||||
|
1 file changed, 60 insertions(+)
|
||||||
|
|
||||||
|
--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi
|
||||||
|
+++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi
|
||||||
|
@@ -38,6 +38,8 @@
|
||||||
|
spi1 = &blsp1_spi2;
|
||||||
|
i2c0 = &blsp1_i2c3;
|
||||||
|
i2c1 = &blsp1_i2c4;
|
||||||
|
+ ethernet0 = &gmac0;
|
||||||
|
+ ethernet1 = &gmac1;
|
||||||
|
};
|
||||||
|
|
||||||
|
cpus {
|
||||||
|
@@ -639,6 +641,64 @@
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
|
+ edma@c080000 {
|
||||||
|
+ compatible = "qcom,ess-edma";
|
||||||
|
+ reg = <0xc080000 0x8000>;
|
||||||
|
+ qcom,page-mode = <0>;
|
||||||
|
+ qcom,rx_head_buf_size = <1540>;
|
||||||
|
+ qcom,mdio_supported;
|
||||||
|
+ qcom,poll_required = <1>;
|
||||||
|
+ qcom,num_gmac = <2>;
|
||||||
|
+ interrupts = <0 65 IRQ_TYPE_EDGE_RISING
|
||||||
|
+ 0 66 IRQ_TYPE_EDGE_RISING
|
||||||
|
+ 0 67 IRQ_TYPE_EDGE_RISING
|
||||||
|
+ 0 68 IRQ_TYPE_EDGE_RISING
|
||||||
|
+ 0 69 IRQ_TYPE_EDGE_RISING
|
||||||
|
+ 0 70 IRQ_TYPE_EDGE_RISING
|
||||||
|
+ 0 71 IRQ_TYPE_EDGE_RISING
|
||||||
|
+ 0 72 IRQ_TYPE_EDGE_RISING
|
||||||
|
+ 0 73 IRQ_TYPE_EDGE_RISING
|
||||||
|
+ 0 74 IRQ_TYPE_EDGE_RISING
|
||||||
|
+ 0 75 IRQ_TYPE_EDGE_RISING
|
||||||
|
+ 0 76 IRQ_TYPE_EDGE_RISING
|
||||||
|
+ 0 77 IRQ_TYPE_EDGE_RISING
|
||||||
|
+ 0 78 IRQ_TYPE_EDGE_RISING
|
||||||
|
+ 0 79 IRQ_TYPE_EDGE_RISING
|
||||||
|
+ 0 80 IRQ_TYPE_EDGE_RISING
|
||||||
|
+ 0 240 IRQ_TYPE_EDGE_RISING
|
||||||
|
+ 0 241 IRQ_TYPE_EDGE_RISING
|
||||||
|
+ 0 242 IRQ_TYPE_EDGE_RISING
|
||||||
|
+ 0 243 IRQ_TYPE_EDGE_RISING
|
||||||
|
+ 0 244 IRQ_TYPE_EDGE_RISING
|
||||||
|
+ 0 245 IRQ_TYPE_EDGE_RISING
|
||||||
|
+ 0 246 IRQ_TYPE_EDGE_RISING
|
||||||
|
+ 0 247 IRQ_TYPE_EDGE_RISING
|
||||||
|
+ 0 248 IRQ_TYPE_EDGE_RISING
|
||||||
|
+ 0 249 IRQ_TYPE_EDGE_RISING
|
||||||
|
+ 0 250 IRQ_TYPE_EDGE_RISING
|
||||||
|
+ 0 251 IRQ_TYPE_EDGE_RISING
|
||||||
|
+ 0 252 IRQ_TYPE_EDGE_RISING
|
||||||
|
+ 0 253 IRQ_TYPE_EDGE_RISING
|
||||||
|
+ 0 254 IRQ_TYPE_EDGE_RISING
|
||||||
|
+ 0 255 IRQ_TYPE_EDGE_RISING>;
|
||||||
|
+
|
||||||
|
+ status = "disabled";
|
||||||
|
+
|
||||||
|
+ gmac0: gmac0 {
|
||||||
|
+ local-mac-address = [00 00 00 00 00 00];
|
||||||
|
+ vlan_tag = <1 0x1f>;
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ gmac1: gmac1 {
|
||||||
|
+ local-mac-address = [00 00 00 00 00 00];
|
||||||
|
+ qcom,phy_mdio_addr = <4>;
|
||||||
|
+ qcom,poll_required = <1>;
|
||||||
|
+ qcom,forced_speed = <1000>;
|
||||||
|
+ qcom,forced_duplex = <1>;
|
||||||
|
+ vlan_tag = <2 0x20>;
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
usb3_ss_phy: ssphy@9a000 {
|
||||||
|
compatible = "qcom,usb-ss-ipq4019-phy";
|
||||||
|
#phy-cells = <0>;
|
|
@ -0,0 +1,205 @@
|
||||||
|
diff --git a/drivers/net/ethernet/qualcomm/essedma/edma.c b/drivers/net/ethernet/qualcomm/essedma/edma.c
|
||||||
|
index 724f355..7a16236 100644
|
||||||
|
--- a/drivers/net/ethernet/qualcomm/essedma/edma.c
|
||||||
|
+++ b/drivers/net/ethernet/qualcomm/essedma/edma.c
|
||||||
|
@@ -22,14 +22,6 @@ extern struct net_device *edma_netdev[EDMA_MAX_PORTID_SUPPORTED];
|
||||||
|
bool edma_stp_rstp;
|
||||||
|
u16 edma_ath_eth_type;
|
||||||
|
|
||||||
|
-/* edma_skb_priority_offset()
|
||||||
|
- * get edma skb priority
|
||||||
|
- */
|
||||||
|
-static unsigned int edma_skb_priority_offset(struct sk_buff *skb)
|
||||||
|
-{
|
||||||
|
- return (skb->priority >> 2) & 1;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
/* edma_alloc_tx_ring()
|
||||||
|
* Allocate Tx descriptors ring
|
||||||
|
*/
|
||||||
|
@@ -1014,13 +1006,14 @@ static inline u16 edma_tpd_available(struct edma_common_info *edma_cinfo,
|
||||||
|
/* edma_tx_queue_get()
|
||||||
|
* Get the starting number of the queue
|
||||||
|
*/
|
||||||
|
-static inline int edma_tx_queue_get(struct edma_adapter *adapter,
|
||||||
|
+static inline int edma_tx_queue_get(struct edma_common_info *edma_cinfo, struct edma_adapter *adapter,
|
||||||
|
struct sk_buff *skb, int txq_id)
|
||||||
|
{
|
||||||
|
/* skb->priority is used as an index to skb priority table
|
||||||
|
* and based on packet priority, correspong queue is assigned.
|
||||||
|
+ * FIXME we just simple use jiffies for time base balance
|
||||||
|
*/
|
||||||
|
- return adapter->tx_start_offset[txq_id] + edma_skb_priority_offset(skb);
|
||||||
|
+ return adapter->tx_start_offset[txq_id] + (smp_processor_id() % edma_cinfo->num_txq_per_core_netdev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* edma_tx_update_hw_idx()
|
||||||
|
@@ -1389,8 +1382,9 @@ netdev_tx_t edma_xmit(struct sk_buff *skb,
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this will be one of the 4 TX queues exposed to linux kernel */
|
||||||
|
- txq_id = skb_get_queue_mapping(skb);
|
||||||
|
- queue_id = edma_tx_queue_get(adapter, skb, txq_id);
|
||||||
|
+ /* XXX what if num_online_cpus() > EDMA_CPU_CORES_SUPPORTED */
|
||||||
|
+ txq_id = ((jiffies >> 5) % (EDMA_CPU_CORES_SUPPORTED - 1) + smp_processor_id() + 1) % EDMA_CPU_CORES_SUPPORTED;
|
||||||
|
+ queue_id = edma_tx_queue_get(edma_cinfo, adapter, skb, txq_id);
|
||||||
|
etdr = edma_cinfo->tpd_ring[queue_id];
|
||||||
|
nq = netdev_get_tx_queue(net_dev, txq_id);
|
||||||
|
|
||||||
|
@@ -1871,8 +1865,8 @@ void edma_free_irqs(struct edma_adapter *adapter)
|
||||||
|
int i, j;
|
||||||
|
int k = ((edma_cinfo->num_rx_queues == 4) ? 1 : 2);
|
||||||
|
|
||||||
|
- for (i = 0; i < CONFIG_NR_CPUS; i++) {
|
||||||
|
- for (j = edma_cinfo->edma_percpu_info[i].tx_start; j < (edma_cinfo->edma_percpu_info[i].tx_start + 4); j++)
|
||||||
|
+ for (i = 0; i < num_online_cpus() && i < EDMA_CPU_CORES_SUPPORTED; i++) {
|
||||||
|
+ for (j = edma_cinfo->edma_percpu_info[i].tx_start; j < (edma_cinfo->edma_percpu_info[i].tx_start + edma_cinfo->num_txq_per_core); j++)
|
||||||
|
free_irq(edma_cinfo->tx_irq[j], &edma_cinfo->edma_percpu_info[i]);
|
||||||
|
|
||||||
|
for (j = edma_cinfo->edma_percpu_info[i].rx_start; j < (edma_cinfo->edma_percpu_info[i].rx_start + k); j++)
|
||||||
|
diff --git a/drivers/net/ethernet/qualcomm/essedma/edma.h b/drivers/net/ethernet/qualcomm/essedma/edma.h
|
||||||
|
index 015e5f5..abb0bd5 100644
|
||||||
|
--- a/drivers/net/ethernet/qualcomm/essedma/edma.h
|
||||||
|
+++ b/drivers/net/ethernet/qualcomm/essedma/edma.h
|
||||||
|
@@ -324,6 +324,7 @@ struct edma_common_info {
|
||||||
|
u32 from_cpu; /* from CPU TPD field */
|
||||||
|
u32 num_rxq_per_core; /* Rx queues per core */
|
||||||
|
u32 num_txq_per_core; /* Tx queues per core */
|
||||||
|
+ u32 num_txq_per_core_netdev; /* Tx queues per core per netdev */
|
||||||
|
u16 tx_ring_count; /* Tx ring count */
|
||||||
|
u16 rx_ring_count; /* Rx ring*/
|
||||||
|
u16 rx_head_buffer_len; /* rx buffer length */
|
||||||
|
@@ -331,7 +332,7 @@ struct edma_common_info {
|
||||||
|
u32 page_mode; /* Jumbo frame supported flag */
|
||||||
|
u32 fraglist_mode; /* fraglist supported flag */
|
||||||
|
struct edma_hw hw; /* edma hw specific structure */
|
||||||
|
- struct edma_per_cpu_queues_info edma_percpu_info[CONFIG_NR_CPUS]; /* per cpu information */
|
||||||
|
+ struct edma_per_cpu_queues_info edma_percpu_info[EDMA_CPU_CORES_SUPPORTED]; /* per cpu information */
|
||||||
|
spinlock_t stats_lock; /* protect edma stats area for updation */
|
||||||
|
struct timer_list edma_stats_timer;
|
||||||
|
bool is_single_phy;
|
||||||
|
@@ -401,7 +402,7 @@ struct edma_adapter {
|
||||||
|
u32 link_state; /* phy link state */
|
||||||
|
u32 phy_mdio_addr; /* PHY device address on MII interface */
|
||||||
|
u32 poll_required; /* check if link polling is required */
|
||||||
|
- u32 tx_start_offset[CONFIG_NR_CPUS]; /* tx queue start */
|
||||||
|
+ u32 tx_start_offset[EDMA_CPU_CORES_SUPPORTED]; /* tx queue start */
|
||||||
|
u32 default_vlan_tag; /* vlan tag */
|
||||||
|
u32 dp_bitmap;
|
||||||
|
uint8_t phy_id[MII_BUS_ID_SIZE + 3];
|
||||||
|
diff --git a/drivers/net/ethernet/qualcomm/essedma/edma_axi.c b/drivers/net/ethernet/qualcomm/essedma/edma_axi.c
|
||||||
|
index d53c63b..2d4770c 100644
|
||||||
|
--- a/drivers/net/ethernet/qualcomm/essedma/edma_axi.c
|
||||||
|
+++ b/drivers/net/ethernet/qualcomm/essedma/edma_axi.c
|
||||||
|
@@ -719,11 +719,7 @@ static int edma_axi_probe(struct platform_device *pdev)
|
||||||
|
int i, j, k, err = 0;
|
||||||
|
int portid_bmp;
|
||||||
|
int idx = 0, idx_mac = 0;
|
||||||
|
-
|
||||||
|
- if (CONFIG_NR_CPUS != EDMA_CPU_CORES_SUPPORTED) {
|
||||||
|
- dev_err(&pdev->dev, "Invalid CPU Cores\n");
|
||||||
|
- return -EINVAL;
|
||||||
|
- }
|
||||||
|
+ int netdev_group = 2;
|
||||||
|
|
||||||
|
if ((num_rxq != 4) && (num_rxq != 8)) {
|
||||||
|
dev_err(&pdev->dev, "Invalid RX queue, edma probe failed\n");
|
||||||
|
@@ -747,7 +743,7 @@ static int edma_axi_probe(struct platform_device *pdev)
|
||||||
|
/* Initialize the netdev array before allocation
|
||||||
|
* to avoid double free
|
||||||
|
*/
|
||||||
|
- for (i = 0 ; i < edma_cinfo->num_gmac ; i++)
|
||||||
|
+ for (i = 0 ; i < EDMA_MAX_PORTID_SUPPORTED; i++)
|
||||||
|
edma_netdev[i] = NULL;
|
||||||
|
|
||||||
|
for (i = 0 ; i < edma_cinfo->num_gmac ; i++) {
|
||||||
|
@@ -768,8 +764,11 @@ static int edma_axi_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
|
/* Fill ring details */
|
||||||
|
edma_cinfo->num_tx_queues = EDMA_MAX_TRANSMIT_QUEUE;
|
||||||
|
- edma_cinfo->num_txq_per_core = (EDMA_MAX_TRANSMIT_QUEUE / 4);
|
||||||
|
+ edma_cinfo->num_txq_per_core = (EDMA_MAX_TRANSMIT_QUEUE / num_online_cpus());
|
||||||
|
+ edma_cinfo->num_txq_per_core_netdev = (EDMA_MAX_TRANSMIT_QUEUE / netdev_group / num_online_cpus());
|
||||||
|
edma_cinfo->tx_ring_count = EDMA_TX_RING_SIZE;
|
||||||
|
+ if (edma_cinfo->num_txq_per_core == 0)
|
||||||
|
+ edma_cinfo->num_txq_per_core = 1;
|
||||||
|
|
||||||
|
/* Update num rx queues based on module parameter */
|
||||||
|
edma_cinfo->num_rx_queues = num_rxq;
|
||||||
|
@@ -939,6 +938,13 @@ static int edma_axi_probe(struct platform_device *pdev)
|
||||||
|
idx_mac++;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (edma_cinfo->num_gmac == 1) {
|
||||||
|
+ netdev_group = 1;
|
||||||
|
+ edma_cinfo->num_txq_per_core_netdev = (EDMA_MAX_TRANSMIT_QUEUE / netdev_group / num_online_cpus());
|
||||||
|
+ }
|
||||||
|
+ if (edma_cinfo->num_txq_per_core_netdev == 0)
|
||||||
|
+ edma_cinfo->num_txq_per_core_netdev = 1;
|
||||||
|
+
|
||||||
|
/* Populate the adapter structure register the netdevice */
|
||||||
|
for (i = 0; i < edma_cinfo->num_gmac; i++) {
|
||||||
|
int k, m;
|
||||||
|
@@ -946,17 +952,16 @@ static int edma_axi_probe(struct platform_device *pdev)
|
||||||
|
adapter[i] = netdev_priv(edma_netdev[i]);
|
||||||
|
adapter[i]->netdev = edma_netdev[i];
|
||||||
|
adapter[i]->pdev = pdev;
|
||||||
|
- for (j = 0; j < CONFIG_NR_CPUS; j++) {
|
||||||
|
- m = i % 2;
|
||||||
|
- adapter[i]->tx_start_offset[j] =
|
||||||
|
- ((j << EDMA_TX_CPU_START_SHIFT) + (m << 1));
|
||||||
|
+ for (j = 0; j < num_online_cpus() && j < EDMA_CPU_CORES_SUPPORTED; j++) {
|
||||||
|
+ m = i % netdev_group;
|
||||||
|
+ adapter[i]->tx_start_offset[j] = j * edma_cinfo->num_txq_per_core + m * edma_cinfo->num_txq_per_core_netdev;
|
||||||
|
/* Share the queues with available net-devices.
|
||||||
|
* For instance , with 5 net-devices
|
||||||
|
* eth0/eth2/eth4 will share q0,q1,q4,q5,q8,q9,q12,q13
|
||||||
|
* and eth1/eth3 will get the remaining.
|
||||||
|
*/
|
||||||
|
for (k = adapter[i]->tx_start_offset[j]; k <
|
||||||
|
- (adapter[i]->tx_start_offset[j] + 2); k++) {
|
||||||
|
+ (adapter[i]->tx_start_offset[j] + edma_cinfo->num_txq_per_core_netdev); k++) {
|
||||||
|
if (edma_fill_netdev(edma_cinfo, k, i, j)) {
|
||||||
|
pr_err("Netdev overflow Error\n");
|
||||||
|
goto err_register;
|
||||||
|
@@ -1109,9 +1114,12 @@ static int edma_axi_probe(struct platform_device *pdev)
|
||||||
|
/* populate per_core_info, do a napi_Add, request 16 TX irqs,
|
||||||
|
* 8 RX irqs, do a napi enable
|
||||||
|
*/
|
||||||
|
- for (i = 0; i < CONFIG_NR_CPUS; i++) {
|
||||||
|
+ for (i = 0; i < num_online_cpus() && i < EDMA_CPU_CORES_SUPPORTED; i++) {
|
||||||
|
u8 rx_start;
|
||||||
|
|
||||||
|
+ tx_mask[i] = (0xFFFF >> (16 - edma_cinfo->num_txq_per_core)) << (i * edma_cinfo->num_txq_per_core);
|
||||||
|
+ tx_start[i] = i * edma_cinfo->num_txq_per_core;
|
||||||
|
+
|
||||||
|
edma_cinfo->edma_percpu_info[i].napi.state = 0;
|
||||||
|
|
||||||
|
netif_napi_add(edma_netdev[0],
|
||||||
|
@@ -1131,7 +1139,7 @@ static int edma_axi_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
|
/* Request irq per core */
|
||||||
|
for (j = edma_cinfo->edma_percpu_info[i].tx_start;
|
||||||
|
- j < tx_start[i] + 4; j++) {
|
||||||
|
+ j < tx_start[i] + edma_cinfo->num_txq_per_core; j++) {
|
||||||
|
sprintf(&edma_tx_irq[j][0], "edma_eth_tx%d", j);
|
||||||
|
err = request_irq(edma_cinfo->tx_irq[j],
|
||||||
|
edma_interrupt,
|
||||||
|
@@ -1253,7 +1261,7 @@ static int edma_axi_probe(struct platform_device *pdev)
|
||||||
|
#endif
|
||||||
|
err_rmap_add_fail:
|
||||||
|
edma_free_irqs(adapter[0]);
|
||||||
|
- for (i = 0; i < CONFIG_NR_CPUS; i++)
|
||||||
|
+ for (i = 0; i < num_online_cpus() && i < EDMA_CPU_CORES_SUPPORTED; i++)
|
||||||
|
napi_disable(&edma_cinfo->edma_percpu_info[i].napi);
|
||||||
|
err_reset:
|
||||||
|
err_unregister_sysctl_tbl:
|
||||||
|
@@ -1301,7 +1309,7 @@ static int edma_axi_remove(struct platform_device *pdev)
|
||||||
|
unregister_netdev(edma_netdev[i]);
|
||||||
|
|
||||||
|
edma_stop_rx_tx(hw);
|
||||||
|
- for (i = 0; i < CONFIG_NR_CPUS; i++)
|
||||||
|
+ for (i = 0; i < num_online_cpus() && i < EDMA_CPU_CORES_SUPPORTED; i++)
|
||||||
|
napi_disable(&edma_cinfo->edma_percpu_info[i].napi);
|
||||||
|
|
||||||
|
edma_irq_disable(edma_cinfo);
|
|
@ -0,0 +1,54 @@
|
||||||
|
diff --git a/drivers/net/ethernet/qualcomm/essedma/edma.c b/drivers/net/ethernet/qualcomm/essedma/edma.c
|
||||||
|
index fc274c8..e9d12a4 100644
|
||||||
|
--- a/drivers/net/ethernet/qualcomm/essedma/edma.c
|
||||||
|
+++ b/drivers/net/ethernet/qualcomm/essedma/edma.c
|
||||||
|
@@ -2075,15 +2075,13 @@ int edma_poll(struct napi_struct *napi, int budget)
|
||||||
|
int i, work_done = 0;
|
||||||
|
u16 rx_pending_fill;
|
||||||
|
|
||||||
|
- /* Store the Rx/Tx status by ANDing it with
|
||||||
|
- * appropriate CPU RX?TX mask
|
||||||
|
+ /* Store the Tx status by ANDing it with
|
||||||
|
+ * appropriate CPU TX mask
|
||||||
|
*/
|
||||||
|
- edma_read_reg(EDMA_REG_RX_ISR, ®_data);
|
||||||
|
- edma_percpu_info->rx_status |= reg_data & edma_percpu_info->rx_mask;
|
||||||
|
- shadow_rx_status = edma_percpu_info->rx_status;
|
||||||
|
edma_read_reg(EDMA_REG_TX_ISR, ®_data);
|
||||||
|
edma_percpu_info->tx_status |= reg_data & edma_percpu_info->tx_mask;
|
||||||
|
shadow_tx_status = edma_percpu_info->tx_status;
|
||||||
|
+ edma_write_reg(EDMA_REG_TX_ISR, shadow_tx_status);
|
||||||
|
|
||||||
|
/* Every core will have a start, which will be computed
|
||||||
|
* in probe and stored in edma_percpu_info->tx_start variable.
|
||||||
|
@@ -2098,6 +2096,14 @@ int edma_poll(struct napi_struct *napi, int budget)
|
||||||
|
edma_percpu_info->tx_status &= ~(1 << queue_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /* Store the Rx status by ANDing it with
|
||||||
|
+ * appropriate CPU RX mask
|
||||||
|
+ */
|
||||||
|
+ edma_read_reg(EDMA_REG_RX_ISR, ®_data);
|
||||||
|
+ edma_percpu_info->rx_status |= reg_data & edma_percpu_info->rx_mask;
|
||||||
|
+ shadow_rx_status = edma_percpu_info->rx_status;
|
||||||
|
+ edma_write_reg(EDMA_REG_RX_ISR, shadow_rx_status);
|
||||||
|
+
|
||||||
|
/* Every core will have a start, which will be computed
|
||||||
|
* in probe and stored in edma_percpu_info->tx_start variable.
|
||||||
|
* We will shift the status bit by tx_start to obtain
|
||||||
|
@@ -2122,15 +2128,6 @@ int edma_poll(struct napi_struct *napi, int budget)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- /* Clear the status register, to avoid the interrupts to
|
||||||
|
- * reoccur.This clearing of interrupt status register is
|
||||||
|
- * done here as writing to status register only takes place
|
||||||
|
- * once the producer/consumer index has been updated to
|
||||||
|
- * reflect that the packet transmission/reception went fine.
|
||||||
|
- */
|
||||||
|
- edma_write_reg(EDMA_REG_RX_ISR, shadow_rx_status);
|
||||||
|
- edma_write_reg(EDMA_REG_TX_ISR, shadow_tx_status);
|
||||||
|
-
|
||||||
|
/* If budget not fully consumed, exit the polling mode */
|
||||||
|
if (likely(work_done < budget)) {
|
||||||
|
napi_complete(napi);
|
|
@ -0,0 +1,69 @@
|
||||||
|
From c611d3780fa101662a822d10acf8feb04ca97409 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Lamparter <chunkeey@gmail.com>
|
||||||
|
Date: Sun, 20 Nov 2016 01:01:10 +0100
|
||||||
|
Subject: [PATCH] dts: ipq4019: add ethernet ipqess node
|
||||||
|
|
||||||
|
This patch adds the device-tree node for the ipqess ethernet
|
||||||
|
interfaces.
|
||||||
|
|
||||||
|
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
|
||||||
|
---
|
||||||
|
arch/arm/boot/dts/qcom-ipq4019.dtsi | 60 +++++++++++++++++++++++++++++++++++++
|
||||||
|
1 file changed, 60 insertions(+)
|
||||||
|
|
||||||
|
--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi
|
||||||
|
+++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi
|
||||||
|
@@ -699,6 +699,53 @@
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
+ gmac: ethernet@c080000 {
|
||||||
|
+ compatible = "qcom,ipq4019-ess-edma";
|
||||||
|
+ reg = <0xc080000 0x8000>;
|
||||||
|
+ interrupts = <GIC_SPI 65 IRQ_TYPE_EDGE_RISING>,
|
||||||
|
+ <GIC_SPI 66 IRQ_TYPE_EDGE_RISING>,
|
||||||
|
+ <GIC_SPI 67 IRQ_TYPE_EDGE_RISING>,
|
||||||
|
+ <GIC_SPI 68 IRQ_TYPE_EDGE_RISING>,
|
||||||
|
+ <GIC_SPI 69 IRQ_TYPE_EDGE_RISING>,
|
||||||
|
+ <GIC_SPI 70 IRQ_TYPE_EDGE_RISING>,
|
||||||
|
+ <GIC_SPI 71 IRQ_TYPE_EDGE_RISING>,
|
||||||
|
+ <GIC_SPI 72 IRQ_TYPE_EDGE_RISING>,
|
||||||
|
+ <GIC_SPI 73 IRQ_TYPE_EDGE_RISING>,
|
||||||
|
+ <GIC_SPI 74 IRQ_TYPE_EDGE_RISING>,
|
||||||
|
+ <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>,
|
||||||
|
+ <GIC_SPI 76 IRQ_TYPE_EDGE_RISING>,
|
||||||
|
+ <GIC_SPI 77 IRQ_TYPE_EDGE_RISING>,
|
||||||
|
+ <GIC_SPI 78 IRQ_TYPE_EDGE_RISING>,
|
||||||
|
+ <GIC_SPI 79 IRQ_TYPE_EDGE_RISING>,
|
||||||
|
+ <GIC_SPI 80 IRQ_TYPE_EDGE_RISING>,
|
||||||
|
+ <GIC_SPI 240 IRQ_TYPE_EDGE_RISING>,
|
||||||
|
+ <GIC_SPI 241 IRQ_TYPE_EDGE_RISING>,
|
||||||
|
+ <GIC_SPI 242 IRQ_TYPE_EDGE_RISING>,
|
||||||
|
+ <GIC_SPI 243 IRQ_TYPE_EDGE_RISING>,
|
||||||
|
+ <GIC_SPI 244 IRQ_TYPE_EDGE_RISING>,
|
||||||
|
+ <GIC_SPI 245 IRQ_TYPE_EDGE_RISING>,
|
||||||
|
+ <GIC_SPI 246 IRQ_TYPE_EDGE_RISING>,
|
||||||
|
+ <GIC_SPI 247 IRQ_TYPE_EDGE_RISING>,
|
||||||
|
+ <GIC_SPI 248 IRQ_TYPE_EDGE_RISING>,
|
||||||
|
+ <GIC_SPI 249 IRQ_TYPE_EDGE_RISING>,
|
||||||
|
+ <GIC_SPI 250 IRQ_TYPE_EDGE_RISING>,
|
||||||
|
+ <GIC_SPI 251 IRQ_TYPE_EDGE_RISING>,
|
||||||
|
+ <GIC_SPI 252 IRQ_TYPE_EDGE_RISING>,
|
||||||
|
+ <GIC_SPI 253 IRQ_TYPE_EDGE_RISING>,
|
||||||
|
+ <GIC_SPI 254 IRQ_TYPE_EDGE_RISING>,
|
||||||
|
+ <GIC_SPI 255 IRQ_TYPE_EDGE_RISING>;
|
||||||
|
+
|
||||||
|
+ status = "disabled";
|
||||||
|
+
|
||||||
|
+ phy-mode = "internal";
|
||||||
|
+ fixed-link {
|
||||||
|
+ speed = <1000>;
|
||||||
|
+ full-duplex;
|
||||||
|
+ pause;
|
||||||
|
+ asym-pause;
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
usb3_ss_phy: ssphy@9a000 {
|
||||||
|
compatible = "qcom,usb-ss-ipq4019-phy";
|
||||||
|
#phy-cells = <0>;
|
|
@ -0,0 +1,180 @@
|
||||||
|
From: Christian Lamparter <chunkeey@googlemail.com>
|
||||||
|
Subject: SoC: add qualcomm syscon
|
||||||
|
--- a/drivers/soc/qcom/Makefile
|
||||||
|
+++ b/drivers/soc/qcom/Makefile
|
||||||
|
@@ -20,6 +20,7 @@ obj-$(CONFIG_QCOM_SMP2P) += smp2p.o
|
||||||
|
obj-$(CONFIG_QCOM_SMSM) += smsm.o
|
||||||
|
obj-$(CONFIG_QCOM_SOCINFO) += socinfo.o
|
||||||
|
obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o
|
||||||
|
+obj-$(CONFIG_QCOM_TCSR) += qcom_tcsr.o
|
||||||
|
obj-$(CONFIG_QCOM_APR) += apr.o
|
||||||
|
obj-$(CONFIG_QCOM_LLCC) += llcc-slice.o
|
||||||
|
obj-$(CONFIG_QCOM_SDM845_LLCC) += llcc-sdm845.o
|
||||||
|
--- a/drivers/soc/qcom/Kconfig
|
||||||
|
+++ b/drivers/soc/qcom/Kconfig
|
||||||
|
@@ -183,6 +183,13 @@ config QCOM_SOCINFO
|
||||||
|
Say yes here to support the Qualcomm socinfo driver, providing
|
||||||
|
information about the SoC to user space.
|
||||||
|
|
||||||
|
+config QCOM_TCSR
|
||||||
|
+ tristate "QCOM Top Control and Status Registers"
|
||||||
|
+ depends on ARCH_QCOM
|
||||||
|
+ help
|
||||||
|
+ Say y here to enable TCSR support. The TCSR provides control
|
||||||
|
+ functions for various peripherals.
|
||||||
|
+
|
||||||
|
config QCOM_WCNSS_CTRL
|
||||||
|
tristate "Qualcomm WCNSS control driver"
|
||||||
|
depends on ARCH_QCOM || COMPILE_TEST
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/drivers/soc/qcom/qcom_tcsr.c
|
||||||
|
@@ -0,0 +1,98 @@
|
||||||
|
+/*
|
||||||
|
+ * Copyright (c) 2014, The Linux foundation. All rights reserved.
|
||||||
|
+ *
|
||||||
|
+ * This program is free software; you can redistribute it and/or modify
|
||||||
|
+ * it under the terms of the GNU General Public License rev 2 and
|
||||||
|
+ * only rev 2 as published by the free Software foundation.
|
||||||
|
+ *
|
||||||
|
+ * This program is distributed in the hope that it will be useful,
|
||||||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ * MERCHANTABILITY or fITNESS fOR A PARTICULAR PURPOSE. See the
|
||||||
|
+ * GNU General Public License for more details.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include <linux/clk.h>
|
||||||
|
+#include <linux/err.h>
|
||||||
|
+#include <linux/io.h>
|
||||||
|
+#include <linux/module.h>
|
||||||
|
+#include <linux/of.h>
|
||||||
|
+#include <linux/of_platform.h>
|
||||||
|
+#include <linux/platform_device.h>
|
||||||
|
+
|
||||||
|
+#define TCSR_USB_PORT_SEL 0xb0
|
||||||
|
+#define TCSR_USB_HSPHY_CONFIG 0xC
|
||||||
|
+
|
||||||
|
+#define TCSR_ESS_INTERFACE_SEL_OFFSET 0x0
|
||||||
|
+#define TCSR_ESS_INTERFACE_SEL_MASK 0xf
|
||||||
|
+
|
||||||
|
+#define TCSR_WIFI0_GLB_CFG_OFFSET 0x0
|
||||||
|
+#define TCSR_WIFI1_GLB_CFG_OFFSET 0x4
|
||||||
|
+#define TCSR_PNOC_SNOC_MEMTYPE_M0_M2 0x4
|
||||||
|
+
|
||||||
|
+static int tcsr_probe(struct platform_device *pdev)
|
||||||
|
+{
|
||||||
|
+ struct resource *res;
|
||||||
|
+ const struct device_node *node = pdev->dev.of_node;
|
||||||
|
+ void __iomem *base;
|
||||||
|
+ u32 val;
|
||||||
|
+
|
||||||
|
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
+ base = devm_ioremap_resource(&pdev->dev, res);
|
||||||
|
+ if (IS_ERR(base))
|
||||||
|
+ return PTR_ERR(base);
|
||||||
|
+
|
||||||
|
+ if (!of_property_read_u32(node, "qcom,usb-ctrl-select", &val)) {
|
||||||
|
+ dev_err(&pdev->dev, "setting usb port select = %d\n", val);
|
||||||
|
+ writel(val, base + TCSR_USB_PORT_SEL);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!of_property_read_u32(node, "qcom,usb-hsphy-mode-select", &val)) {
|
||||||
|
+ dev_info(&pdev->dev, "setting usb hs phy mode select = %x\n", val);
|
||||||
|
+ writel(val, base + TCSR_USB_HSPHY_CONFIG);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!of_property_read_u32(node, "qcom,ess-interface-select", &val)) {
|
||||||
|
+ u32 tmp = 0;
|
||||||
|
+ dev_info(&pdev->dev, "setting ess interface select = %x\n", val);
|
||||||
|
+ tmp = readl(base + TCSR_ESS_INTERFACE_SEL_OFFSET);
|
||||||
|
+ tmp = tmp & (~TCSR_ESS_INTERFACE_SEL_MASK);
|
||||||
|
+ tmp = tmp | (val&TCSR_ESS_INTERFACE_SEL_MASK);
|
||||||
|
+ writel(tmp, base + TCSR_ESS_INTERFACE_SEL_OFFSET);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!of_property_read_u32(node, "qcom,wifi_glb_cfg", &val)) {
|
||||||
|
+ dev_info(&pdev->dev, "setting wifi_glb_cfg = %x\n", val);
|
||||||
|
+ writel(val, base + TCSR_WIFI0_GLB_CFG_OFFSET);
|
||||||
|
+ writel(val, base + TCSR_WIFI1_GLB_CFG_OFFSET);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!of_property_read_u32(node, "qcom,wifi_noc_memtype_m0_m2", &val)) {
|
||||||
|
+ dev_info(&pdev->dev,
|
||||||
|
+ "setting wifi_noc_memtype_m0_m2 = %x\n", val);
|
||||||
|
+ writel(val, base + TCSR_PNOC_SNOC_MEMTYPE_M0_M2);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static const struct of_device_id tcsr_dt_match[] = {
|
||||||
|
+ { .compatible = "qcom,tcsr", },
|
||||||
|
+ { },
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+MODULE_DEVICE_TABLE(of, tcsr_dt_match);
|
||||||
|
+
|
||||||
|
+static struct platform_driver tcsr_driver = {
|
||||||
|
+ .driver = {
|
||||||
|
+ .name = "tcsr",
|
||||||
|
+ .owner = THIS_MODULE,
|
||||||
|
+ .of_match_table = tcsr_dt_match,
|
||||||
|
+ },
|
||||||
|
+ .probe = tcsr_probe,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+module_platform_driver(tcsr_driver);
|
||||||
|
+
|
||||||
|
+MODULE_AUTHOR("Andy Gross <agross@codeaurora.org>");
|
||||||
|
+MODULE_DESCRIPTION("QCOM TCSR driver");
|
||||||
|
+MODULE_LICENSE("GPL v2");
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/include/dt-bindings/soc/qcom,tcsr.h
|
||||||
|
@@ -0,0 +1,48 @@
|
||||||
|
+/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
|
||||||
|
+ *
|
||||||
|
+ * This program is free software; you can redistribute it and/or modify
|
||||||
|
+ * it under the terms of the GNU General Public License version 2 and
|
||||||
|
+ * only version 2 as published by the Free Software Foundation.
|
||||||
|
+ *
|
||||||
|
+ * This program is distributed in the hope that it will be useful,
|
||||||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
+ * GNU General Public License for more details.
|
||||||
|
+ */
|
||||||
|
+#ifndef __DT_BINDINGS_QCOM_TCSR_H
|
||||||
|
+#define __DT_BINDINGS_QCOM_TCSR_H
|
||||||
|
+
|
||||||
|
+#define TCSR_USB_SELECT_USB3_P0 0x1
|
||||||
|
+#define TCSR_USB_SELECT_USB3_P1 0x2
|
||||||
|
+#define TCSR_USB_SELECT_USB3_DUAL 0x3
|
||||||
|
+
|
||||||
|
+/* IPQ40xx HS PHY Mode Select */
|
||||||
|
+#define TCSR_USB_HSPHY_HOST_MODE 0x00E700E7
|
||||||
|
+#define TCSR_USB_HSPHY_DEVICE_MODE 0x00C700E7
|
||||||
|
+
|
||||||
|
+/* IPQ40xx ess interface mode select */
|
||||||
|
+#define TCSR_ESS_PSGMII 0
|
||||||
|
+#define TCSR_ESS_PSGMII_RGMII5 1
|
||||||
|
+#define TCSR_ESS_PSGMII_RMII0 2
|
||||||
|
+#define TCSR_ESS_PSGMII_RMII1 4
|
||||||
|
+#define TCSR_ESS_PSGMII_RMII0_RMII1 6
|
||||||
|
+#define TCSR_ESS_PSGMII_RGMII4 9
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * IPQ40xx WiFi Global Config
|
||||||
|
+ * Bit 30:AXID_EN
|
||||||
|
+ * Enable AXI master bus Axid translating to confirm all txn submitted by order
|
||||||
|
+ * Bit 24: Use locally generated socslv_wxi_bvalid
|
||||||
|
+ * 1: use locally generate socslv_wxi_bvalid for performance.
|
||||||
|
+ * 0: use SNOC socslv_wxi_bvalid.
|
||||||
|
+ */
|
||||||
|
+#define TCSR_WIFI_GLB_CFG 0x41000000
|
||||||
|
+
|
||||||
|
+/* IPQ40xx MEM_TYPE_SEL_M0_M2 Select Bit 26:24 - 2 NORMAL */
|
||||||
|
+#define TCSR_WIFI_NOC_MEMTYPE_M0_M2 0x02222222
|
||||||
|
+
|
||||||
|
+/* TCSR A/B REG */
|
||||||
|
+#define IPQ806X_TCSR_REG_A_ADM_CRCI_MUX_SEL 0
|
||||||
|
+#define IPQ806X_TCSR_REG_B_ADM_CRCI_MUX_SEL 1
|
||||||
|
+
|
||||||
|
+#endif
|
|
@ -0,0 +1,157 @@
|
||||||
|
--- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi
|
||||||
|
+++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi
|
||||||
|
@@ -15,6 +15,7 @@
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qcom-ipq4019.dtsi"
|
||||||
|
+#include <dt-bindings/soc/qcom,tcsr.h>
|
||||||
|
|
||||||
|
/ {
|
||||||
|
model = "Qualcomm Technologies, Inc. IPQ4019/AP-DK01.1";
|
||||||
|
@@ -29,6 +30,32 @@
|
||||||
|
};
|
||||||
|
|
||||||
|
soc {
|
||||||
|
+ tcsr@194b000 {
|
||||||
|
+ /* select hostmode */
|
||||||
|
+ compatible = "qcom,tcsr";
|
||||||
|
+ reg = <0x194b000 0x100>;
|
||||||
|
+ qcom,usb-hsphy-mode-select = <TCSR_USB_HSPHY_HOST_MODE>;
|
||||||
|
+ status = "okay";
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ ess_tcsr@1953000 {
|
||||||
|
+ compatible = "qcom,tcsr";
|
||||||
|
+ reg = <0x1953000 0x1000>;
|
||||||
|
+ qcom,ess-interface-select = <TCSR_ESS_PSGMII>;
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ tcsr@1949000 {
|
||||||
|
+ compatible = "qcom,tcsr";
|
||||||
|
+ reg = <0x1949000 0x100>;
|
||||||
|
+ qcom,wifi_glb_cfg = <TCSR_WIFI_GLB_CFG>;
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ tcsr@1957000 {
|
||||||
|
+ compatible = "qcom,tcsr";
|
||||||
|
+ reg = <0x1957000 0x100>;
|
||||||
|
+ qcom,wifi_noc_memtype_m0_m2 = <TCSR_WIFI_NOC_MEMTYPE_M0_M2>;
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
rng@22000 {
|
||||||
|
status = "ok";
|
||||||
|
};
|
||||||
|
@@ -74,14 +101,6 @@
|
||||||
|
pinctrl-names = "default";
|
||||||
|
status = "ok";
|
||||||
|
cs-gpios = <&tlmm 54 0>;
|
||||||
|
-
|
||||||
|
- mx25l25635e@0 {
|
||||||
|
- #address-cells = <1>;
|
||||||
|
- #size-cells = <1>;
|
||||||
|
- reg = <0>;
|
||||||
|
- compatible = "mx25l25635e";
|
||||||
|
- spi-max-frequency = <24000000>;
|
||||||
|
- };
|
||||||
|
};
|
||||||
|
|
||||||
|
serial@78af000 {
|
||||||
|
@@ -110,6 +129,22 @@
|
||||||
|
status = "ok";
|
||||||
|
};
|
||||||
|
|
||||||
|
+ mdio@90000 {
|
||||||
|
+ status = "okay";
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ ess-switch@c000000 {
|
||||||
|
+ status = "okay";
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ ess-psgmii@98000 {
|
||||||
|
+ status = "okay";
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ edma@c080000 {
|
||||||
|
+ status = "okay";
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
usb3_ss_phy: ssphy@9a000 {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
--- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1-c1.dts
|
||||||
|
+++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1-c1.dts
|
||||||
|
@@ -18,5 +18,73 @@
|
||||||
|
|
||||||
|
/ {
|
||||||
|
model = "Qualcomm Technologies, Inc. IPQ40xx/AP-DK01.1-C1";
|
||||||
|
+ compatible = "qcom,ap-dk01.1-c1", "qcom,ap-dk01.2-c1";
|
||||||
|
|
||||||
|
+ memory {
|
||||||
|
+ device_type = "memory";
|
||||||
|
+ reg = <0x80000000 0x10000000>;
|
||||||
|
+ };
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+&blsp1_spi1 {
|
||||||
|
+ mx25l25635f@0 {
|
||||||
|
+ compatible = "mx25l25635f", "jedec,spi-nor";
|
||||||
|
+ #address-cells = <1>;
|
||||||
|
+ #size-cells = <1>;
|
||||||
|
+ reg = <0>;
|
||||||
|
+ spi-max-frequency = <24000000>;
|
||||||
|
+
|
||||||
|
+ SBL1@0 {
|
||||||
|
+ label = "SBL1";
|
||||||
|
+ reg = <0x0 0x40000>;
|
||||||
|
+ read-only;
|
||||||
|
+ };
|
||||||
|
+ MIBIB@40000 {
|
||||||
|
+ label = "MIBIB";
|
||||||
|
+ reg = <0x40000 0x20000>;
|
||||||
|
+ read-only;
|
||||||
|
+ };
|
||||||
|
+ QSEE@60000 {
|
||||||
|
+ label = "QSEE";
|
||||||
|
+ reg = <0x60000 0x60000>;
|
||||||
|
+ read-only;
|
||||||
|
+ };
|
||||||
|
+ CDT@c0000 {
|
||||||
|
+ label = "CDT";
|
||||||
|
+ reg = <0xc0000 0x10000>;
|
||||||
|
+ read-only;
|
||||||
|
+ };
|
||||||
|
+ DDRPARAMS@d0000 {
|
||||||
|
+ label = "DDRPARAMS";
|
||||||
|
+ reg = <0xd0000 0x10000>;
|
||||||
|
+ read-only;
|
||||||
|
+ };
|
||||||
|
+ APPSBLENV@e0000 {
|
||||||
|
+ label = "APPSBLENV";
|
||||||
|
+ reg = <0xe0000 0x10000>;
|
||||||
|
+ read-only;
|
||||||
|
+ };
|
||||||
|
+ APPSBL@f0000 {
|
||||||
|
+ label = "APPSBL";
|
||||||
|
+ reg = <0xf0000 0x80000>;
|
||||||
|
+ read-only;
|
||||||
|
+ };
|
||||||
|
+ ART@170000 {
|
||||||
|
+ label = "ART";
|
||||||
|
+ reg = <0x170000 0x10000>;
|
||||||
|
+ read-only;
|
||||||
|
+ };
|
||||||
|
+ kernel@180000 {
|
||||||
|
+ label = "kernel";
|
||||||
|
+ reg = <0x180000 0x400000>;
|
||||||
|
+ };
|
||||||
|
+ rootfs@580000 {
|
||||||
|
+ label = "rootfs";
|
||||||
|
+ reg = <0x580000 0x1600000>;
|
||||||
|
+ };
|
||||||
|
+ firmware@180000 {
|
||||||
|
+ label = "firmware";
|
||||||
|
+ reg = <0x180000 0x1a00000>;
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
};
|
|
@ -0,0 +1,12 @@
|
||||||
|
--- a/drivers/of/fdt.c
|
||||||
|
+++ b/drivers/of/fdt.c
|
||||||
|
@@ -1059,6 +1059,9 @@ int __init early_init_dt_scan_chosen(uns
|
||||||
|
p = of_get_flat_dt_prop(node, "bootargs", &l);
|
||||||
|
if (p != NULL && l > 0)
|
||||||
|
strlcpy(data, p, min(l, COMMAND_LINE_SIZE));
|
||||||
|
+ p = of_get_flat_dt_prop(node, "bootargs-append", &l);
|
||||||
|
+ if (p != NULL && l > 0)
|
||||||
|
+ strlcat(data, p, min_t(int, strlen(data) + (int)l, COMMAND_LINE_SIZE));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CONFIG_CMDLINE is meant to be a default in case nothing else
|
Loading…
Add table
Add a link
Reference in a new issue