summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/clk/microchip/mpfs_clk.c1
-rw-r--r--drivers/crypto/fsl/Kconfig6
-rw-r--r--drivers/crypto/fsl/Makefile4
-rw-r--r--drivers/crypto/fsl/desc.h49
-rw-r--r--drivers/crypto/fsl/desc_constr.h28
-rw-r--r--drivers/crypto/fsl/fsl_blob.c6
-rw-r--r--drivers/crypto/fsl/fsl_hash.c6
-rw-r--r--drivers/crypto/fsl/fsl_mfgprot.c160
-rw-r--r--drivers/crypto/fsl/jobdesc.c16
-rw-r--r--drivers/crypto/fsl/jr.c53
-rw-r--r--drivers/crypto/fsl/jr.h11
-rw-r--r--drivers/crypto/fsl/type.h16
-rw-r--r--drivers/ddr/imx/imx8m/Kconfig8
-rw-r--r--drivers/misc/mxc_ocotp.c2
-rw-r--r--drivers/mmc/Kconfig9
-rw-r--r--drivers/mmc/fsl_esdhc_imx.c50
-rw-r--r--drivers/mmc/mvebu_mmc.c307
-rw-r--r--drivers/mtd/nand/raw/mxs_nand_spl.c5
-rw-r--r--drivers/power/pmic/pmic_pca9450.c4
-rw-r--r--drivers/ram/sifive/Kconfig2
-rw-r--r--drivers/reset/Kconfig2
-rw-r--r--drivers/rtc/Kconfig7
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/armada38x.c184
-rw-r--r--drivers/timer/sifive_clint_timer.c1
-rw-r--r--drivers/watchdog/designware_wdt.c37
26 files changed, 735 insertions, 240 deletions
diff --git a/drivers/clk/microchip/mpfs_clk.c b/drivers/clk/microchip/mpfs_clk.c
index 722c79b7c0e..05d7647206c 100644
--- a/drivers/clk/microchip/mpfs_clk.c
+++ b/drivers/clk/microchip/mpfs_clk.c
@@ -120,4 +120,5 @@ U_BOOT_DRIVER(mpfs_clk) = {
.ops = &mpfs_clk_ops,
.probe = mpfs_clk_probe,
.priv_auto = sizeof(struct clk),
+ .flags = DM_FLAG_PRE_RELOC,
};
diff --git a/drivers/crypto/fsl/Kconfig b/drivers/crypto/fsl/Kconfig
index 5ed6140da35..1f5dfb94bb8 100644
--- a/drivers/crypto/fsl/Kconfig
+++ b/drivers/crypto/fsl/Kconfig
@@ -7,6 +7,12 @@ config FSL_CAAM
Module (CAAM), also known as the SEC version 4 (SEC4). The driver uses
Job Ring as interface to communicate with CAAM.
+config CAAM_64BIT
+ bool
+ default y if PHYS_64BIT && !ARCH_IMX8M
+ help
+ Select Crypto driver for 64 bits CAAM version
+
config SYS_FSL_HAS_SEC
bool
help
diff --git a/drivers/crypto/fsl/Makefile b/drivers/crypto/fsl/Makefile
index a5e8d38e381..f9c3ccecfc2 100644
--- a/drivers/crypto/fsl/Makefile
+++ b/drivers/crypto/fsl/Makefile
@@ -4,7 +4,7 @@
obj-y += sec.o
obj-$(CONFIG_FSL_CAAM) += jr.o fsl_hash.o jobdesc.o error.o
-obj-$(CONFIG_CMD_BLOB) += fsl_blob.o
-obj-$(CONFIG_CMD_DEKBLOB) += fsl_blob.o
+obj-$(CONFIG_CMD_BLOB)$(CONFIG_IMX_CAAM_DEK_ENCAP) += fsl_blob.o
obj-$(CONFIG_RSA_FREESCALE_EXP) += fsl_rsa.o
obj-$(CONFIG_FSL_CAAM_RNG) += rng.o
+obj-$(CONFIG_FSL_MFGPROT) += fsl_mfgprot.o
diff --git a/drivers/crypto/fsl/desc.h b/drivers/crypto/fsl/desc.h
index 3589e6ea024..5705c4f9447 100644
--- a/drivers/crypto/fsl/desc.h
+++ b/drivers/crypto/fsl/desc.h
@@ -11,6 +11,8 @@
#ifndef DESC_H
#define DESC_H
+#include "type.h"
+
#define KEY_BLOB_SIZE 32
#define MAC_SIZE 16
@@ -693,29 +695,29 @@
/* Structures for Protocol Data Blocks */
struct __packed pdb_ecdsa_verify {
uint32_t pdb_hdr;
- dma_addr_t dma_q; /* Pointer to q (elliptic curve) */
- dma_addr_t dma_r; /* Pointer to r (elliptic curve) */
- dma_addr_t dma_g_xy; /* Pointer to Gx,y (elliptic curve) */
- dma_addr_t dma_pkey; /* Pointer to Wx,y (public key) */
- dma_addr_t dma_hash; /* Pointer to hash input */
- dma_addr_t dma_c; /* Pointer to C_signature */
- dma_addr_t dma_d; /* Pointer to D_signature */
- dma_addr_t dma_buf; /* Pointer to 64-byte temp buffer */
- dma_addr_t dma_ab; /* Pointer to a,b (elliptic curve ) */
+ caam_dma_addr_t dma_q; /* Pointer to q (elliptic curve) */
+ caam_dma_addr_t dma_r; /* Pointer to r (elliptic curve) */
+ caam_dma_addr_t dma_g_xy; /* Pointer to Gx,y (elliptic curve) */
+ caam_dma_addr_t dma_pkey; /* Pointer to Wx,y (public key) */
+ caam_dma_addr_t dma_hash; /* Pointer to hash input */
+ caam_dma_addr_t dma_c; /* Pointer to C_signature */
+ caam_dma_addr_t dma_d; /* Pointer to D_signature */
+ caam_dma_addr_t dma_buf; /* Pointer to 64-byte temp buffer */
+ caam_dma_addr_t dma_ab; /* Pointer to a,b (elliptic curve ) */
uint32_t img_size; /* Length of Message */
};
struct __packed pdb_ecdsa_sign {
uint32_t pdb_hdr;
- dma_addr_t dma_q; /* Pointer to q (elliptic curve) */
- dma_addr_t dma_r; /* Pointer to r (elliptic curve) */
- dma_addr_t dma_g_xy; /* Pointer to Gx,y (elliptic curve) */
- dma_addr_t dma_pri_key; /* Pointer to S (Private key) */
- dma_addr_t dma_hash; /* Pointer to hash input */
- dma_addr_t dma_c; /* Pointer to C_signature */
- dma_addr_t dma_d; /* Pointer to D_signature */
- dma_addr_t dma_ab; /* Pointer to a,b (elliptic curve ) */
- dma_addr_t dma_u; /* Pointer to Per Message Random */
+ caam_dma_addr_t dma_q; /* Pointer to q (elliptic curve) */
+ caam_dma_addr_t dma_r; /* Pointer to r (elliptic curve) */
+ caam_dma_addr_t dma_g_xy; /* Pointer to Gx,y (elliptic curve) */
+ caam_dma_addr_t dma_pri_key; /* Pointer to S (Private key) */
+ caam_dma_addr_t dma_hash; /* Pointer to hash input */
+ caam_dma_addr_t dma_c; /* Pointer to C_signature */
+ caam_dma_addr_t dma_d; /* Pointer to D_signature */
+ caam_dma_addr_t dma_ab; /* Pointer to a,b (elliptic curve ) */
+ caam_dma_addr_t dma_u; /* Pointer to Per Message Random */
uint32_t img_size; /* Length of Message */
};
@@ -726,20 +728,21 @@ struct __packed pdb_ecdsa_sign {
struct __packed pdb_mp_pub_k {
uint32_t pdb_hdr;
#define PDB_MP_PUB_K_SGF_SHIFT 31
- dma_addr_t dma_pkey; /* Pointer to Wx,y (public key) */
+ caam_dma_addr_t dma_pkey; /* Pointer to Wx,y (public key) */
};
struct __packed pdb_mp_sign {
uint32_t pdb_hdr;
#define PDB_MP_SIGN_SGF_SHIFT 28
- dma_addr_t dma_addr_msg; /* Pointer to Message */
- dma_addr_t dma_addr_hash; /* Pointer to hash output */
- dma_addr_t dma_addr_c_sig; /* Pointer to C_signature */
- dma_addr_t dma_addr_d_sig; /* Pointer to D_signature */
+ caam_dma_addr_t dma_addr_msg; /* Pointer to Message */
+ caam_dma_addr_t dma_addr_hash; /* Pointer to hash output */
+ caam_dma_addr_t dma_addr_c_sig; /* Pointer to C_signature */
+ caam_dma_addr_t dma_addr_d_sig; /* Pointer to D_signature */
uint32_t img_size; /* Length of Message */
};
#define PDB_MP_CSEL_SHIFT 17
+#define PDB_MP_CSEL_WIDTH 4
#define PDB_MP_CSEL_P256 0x3 << PDB_MP_CSEL_SHIFT /* P-256 */
#define PDB_MP_CSEL_P384 0x4 << PDB_MP_CSEL_SHIFT /* P-384 */
#define PDB_MP_CSEL_P521 0x5 << PDB_MP_CSEL_SHIFT /* P-521 */
diff --git a/drivers/crypto/fsl/desc_constr.h b/drivers/crypto/fsl/desc_constr.h
index b82ba83e73a..209557c4ffa 100644
--- a/drivers/crypto/fsl/desc_constr.h
+++ b/drivers/crypto/fsl/desc_constr.h
@@ -12,7 +12,7 @@
#define IMMEDIATE (1 << 23)
#define CAAM_CMD_SZ sizeof(u32)
-#define CAAM_PTR_SZ sizeof(dma_addr_t)
+#define CAAM_PTR_SZ sizeof(caam_dma_addr_t)
#define CAAM_DESC_BYTES_MAX (CAAM_CMD_SZ * MAX_CAAM_DESCSIZE)
#define DESC_JOB_IO_LEN (CAAM_CMD_SZ * 5 + CAAM_PTR_SZ * 3)
@@ -35,7 +35,7 @@
LDST_SRCDST_WORD_DECOCTRL | \
(LDOFF_ENABLE_AUTO_NFIFO << LDST_OFFSET_SHIFT))
-#ifdef CONFIG_PHYS_64BIT
+#ifdef CONFIG_CAAM_64BIT
struct ptr_addr_t {
#ifdef CONFIG_SYS_FSL_SEC_LE
u32 low;
@@ -49,9 +49,9 @@ struct ptr_addr_t {
};
#endif
-static inline void pdb_add_ptr(dma_addr_t *offset, dma_addr_t ptr)
+static inline void pdb_add_ptr(caam_dma_addr_t *offset, caam_dma_addr_t ptr)
{
-#ifdef CONFIG_PHYS_64BIT
+#ifdef CONFIG_CAAM_64BIT
/* The Position of low and high part of 64 bit address
* will depend on the endianness of CAAM Block */
struct ptr_addr_t *ptr_addr = (struct ptr_addr_t *)offset;
@@ -102,11 +102,11 @@ static inline void init_job_desc_pdb(u32 *desc, u32 options, size_t pdb_bytes)
options);
}
-static inline void append_ptr(u32 *desc, dma_addr_t ptr)
+static inline void append_ptr(u32 *desc, caam_dma_addr_t ptr)
{
- dma_addr_t *offset = (dma_addr_t *)desc_end(desc);
+ caam_dma_addr_t *offset = (caam_dma_addr_t *)desc_end(desc);
-#ifdef CONFIG_PHYS_64BIT
+#ifdef CONFIG_CAAM_64BIT
/* The Position of low and high part of 64 bit address
* will depend on the endianness of CAAM Block */
struct ptr_addr_t *ptr_addr = (struct ptr_addr_t *)offset;
@@ -159,7 +159,7 @@ static inline u32 *write_cmd(u32 *desc, u32 command)
return desc + 1;
}
-static inline void append_cmd_ptr(u32 *desc, dma_addr_t ptr, int len,
+static inline void append_cmd_ptr(u32 *desc, caam_dma_addr_t ptr, int len,
u32 command)
{
append_cmd(desc, command | len);
@@ -167,7 +167,7 @@ static inline void append_cmd_ptr(u32 *desc, dma_addr_t ptr, int len,
}
/* Write length after pointer, rather than inside command */
-static inline void append_cmd_ptr_extlen(u32 *desc, dma_addr_t ptr,
+static inline void append_cmd_ptr_extlen(u32 *desc, caam_dma_addr_t ptr,
unsigned int len, u32 command)
{
append_cmd(desc, command);
@@ -225,7 +225,7 @@ APPEND_CMD_LEN(seq_fifo_load, SEQ_FIFO_LOAD)
APPEND_CMD_LEN(seq_fifo_store, SEQ_FIFO_STORE)
#define APPEND_CMD_PTR(cmd, op) \
-static inline void append_##cmd(u32 *desc, dma_addr_t ptr, unsigned int len, \
+static inline void append_##cmd(u32 *desc, caam_dma_addr_t ptr, unsigned int len, \
u32 options) \
{ \
PRINT_POS; \
@@ -236,7 +236,7 @@ APPEND_CMD_PTR(load, LOAD)
APPEND_CMD_PTR(fifo_load, FIFO_LOAD)
APPEND_CMD_PTR(fifo_store, FIFO_STORE)
-static inline void append_store(u32 *desc, dma_addr_t ptr, unsigned int len,
+static inline void append_store(u32 *desc, caam_dma_addr_t ptr, unsigned int len,
u32 options)
{
u32 cmd_src;
@@ -254,7 +254,7 @@ static inline void append_store(u32 *desc, dma_addr_t ptr, unsigned int len,
}
#define APPEND_SEQ_PTR_INTLEN(cmd, op) \
-static inline void append_seq_##cmd##_ptr_intlen(u32 *desc, dma_addr_t ptr, \
+static inline void append_seq_##cmd##_ptr_intlen(u32 *desc, caam_dma_addr_t ptr, \
unsigned int len, \
u32 options) \
{ \
@@ -278,7 +278,7 @@ APPEND_CMD_PTR_TO_IMM(load, LOAD);
APPEND_CMD_PTR_TO_IMM(fifo_load, FIFO_LOAD);
#define APPEND_CMD_PTR_EXTLEN(cmd, op) \
-static inline void append_##cmd##_extlen(u32 *desc, dma_addr_t ptr, \
+static inline void append_##cmd##_extlen(u32 *desc, caam_dma_addr_t ptr, \
unsigned int len, u32 options) \
{ \
PRINT_POS; \
@@ -292,7 +292,7 @@ APPEND_CMD_PTR_EXTLEN(seq_out_ptr, SEQ_OUT_PTR)
* the size of its type
*/
#define APPEND_CMD_PTR_LEN(cmd, op, type) \
-static inline void append_##cmd(u32 *desc, dma_addr_t ptr, \
+static inline void append_##cmd(u32 *desc, caam_dma_addr_t ptr, \
type len, u32 options) \
{ \
PRINT_POS; \
diff --git a/drivers/crypto/fsl/fsl_blob.c b/drivers/crypto/fsl/fsl_blob.c
index d6bd861251e..e8202cc5697 100644
--- a/drivers/crypto/fsl/fsl_blob.c
+++ b/drivers/crypto/fsl/fsl_blob.c
@@ -65,6 +65,9 @@ int blob_decap(u8 *key_mod, u8 *src, u8 *dst, u32 len)
flush_dcache_range((unsigned long)desc,
(unsigned long)desc + size);
+ flush_dcache_range((unsigned long)dst,
+ (unsigned long)dst + size);
+
ret = run_descriptor_jr(desc);
if (ret) {
@@ -130,6 +133,9 @@ int blob_encap(u8 *key_mod, u8 *src, u8 *dst, u32 len)
flush_dcache_range((unsigned long)desc,
(unsigned long)desc + size);
+ flush_dcache_range((unsigned long)dst,
+ (unsigned long)dst + size);
+
ret = run_descriptor_jr(desc);
if (ret) {
diff --git a/drivers/crypto/fsl/fsl_hash.c b/drivers/crypto/fsl/fsl_hash.c
index 61f953e8a6d..8b5c26db070 100644
--- a/drivers/crypto/fsl/fsl_hash.c
+++ b/drivers/crypto/fsl/fsl_hash.c
@@ -87,7 +87,7 @@ static int caam_hash_update(void *hash_ctx, const void *buf,
enum caam_hash_algos caam_algo)
{
uint32_t final;
- phys_addr_t addr = virt_to_phys((void *)buf);
+ caam_dma_addr_t addr = virt_to_phys((void *)buf);
struct sha_ctx *ctx = hash_ctx;
if (ctx->sg_num >= MAX_SG_32) {
@@ -95,12 +95,12 @@ static int caam_hash_update(void *hash_ctx, const void *buf,
return -EINVAL;
}
-#ifdef CONFIG_PHYS_64BIT
+#ifdef CONFIG_CAAM_64BIT
sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_hi, (uint32_t)(addr >> 32));
#else
sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_hi, 0x0);
#endif
- sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_lo, (uint32_t)addr);
+ sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_lo, (caam_dma_addr_t)addr);
sec_out32(&ctx->sg_tbl[ctx->sg_num].len_flag,
(size & SG_ENTRY_LENGTH_MASK));
diff --git a/drivers/crypto/fsl/fsl_mfgprot.c b/drivers/crypto/fsl/fsl_mfgprot.c
new file mode 100644
index 00000000000..29af79f577d
--- /dev/null
+++ b/drivers/crypto/fsl/fsl_mfgprot.c
@@ -0,0 +1,160 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2014-2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <fsl_sec.h>
+#include <memalign.h>
+#include "desc.h"
+#include "desc_constr.h"
+#include "jobdesc.h"
+#include "jr.h"
+
+/* Size of MFG descriptor */
+#define MFG_PUBK_DSC_WORDS 4
+#define MFG_SIGN_DSC_WORDS 8
+
+static void mfg_build_sign_dsc(u32 *dsc_ptr, const u8 *m, int size,
+ u8 *dgst, u8 *c, u8 *d)
+{
+ u32 *dsc = dsc_ptr;
+ struct pdb_mp_sign *pdb;
+
+ init_job_desc_pdb(dsc, 0, sizeof(struct pdb_mp_sign));
+
+ pdb = (struct pdb_mp_sign *)desc_pdb(dsc);
+
+ /* Curve */
+ pdb->pdb_hdr = (PDB_MP_CSEL_P256);
+
+ /* Message Pointer */
+ pdb_add_ptr(&pdb->dma_addr_msg, virt_to_phys((void *)m));
+
+ /* mes-resp Pointer */
+ pdb_add_ptr(&pdb->dma_addr_hash, virt_to_phys((void *)dgst));
+
+ /* C Pointer */
+ pdb_add_ptr(&pdb->dma_addr_c_sig, virt_to_phys((void *)c));
+
+ /* d Pointer */
+ pdb_add_ptr(&pdb->dma_addr_d_sig, virt_to_phys((void *)d));
+
+ /* Message Size */
+ pdb->img_size = size;
+
+ /* MP PubK generate key command */
+ append_cmd(dsc, (CMD_OPERATION | OP_TYPE_DECAP_PROTOCOL |
+ OP_PCLID_MP_SIGN));
+}
+
+static void mfg_build_pubk_dsc(u32 *dsc_ptr, u8 *dst)
+{
+ u32 *dsc = dsc_ptr;
+ struct pdb_mp_pub_k *pdb;
+
+ init_job_desc_pdb(dsc, 0, sizeof(struct pdb_mp_pub_k));
+
+ pdb = (struct pdb_mp_pub_k *)desc_pdb(dsc);
+
+ /* Curve */
+ pdb->pdb_hdr = (PDB_MP_CSEL_P256);
+
+ /* Message Pointer */
+ pdb_add_ptr(&pdb->dma_pkey, virt_to_phys((void *)dst));
+
+ /* MP Sign key command */
+ append_cmd(dsc, (CMD_OPERATION | OP_TYPE_DECAP_PROTOCOL |
+ OP_PCLID_MP_PUB_KEY));
+}
+
+int gen_mppubk(u8 *dst)
+{
+ int size, ret;
+ u32 *dsc;
+
+ /* Job Descriptor initialization */
+ dsc = memalign(ARCH_DMA_MINALIGN,
+ sizeof(uint32_t) * MFG_PUBK_DSC_WORDS);
+ if (!dsc) {
+ debug("Not enough memory for descriptor allocation\n");
+ return -ENOMEM;
+ }
+
+ mfg_build_pubk_dsc(dsc, dst);
+
+ size = roundup(sizeof(uint32_t) * MFG_PUBK_DSC_WORDS,
+ ARCH_DMA_MINALIGN);
+ flush_dcache_range((unsigned long)dsc, (unsigned long)dsc + size);
+
+ size = roundup(FSL_CAAM_MP_PUBK_BYTES, ARCH_DMA_MINALIGN);
+ flush_dcache_range((unsigned long)dst, (unsigned long)dst + size);
+
+ /* Execute Job Descriptor */
+ puts("\nGenerating Manufacturing Protection Public Key\n");
+
+ ret = run_descriptor_jr(dsc);
+ if (ret) {
+ debug("Error in public key generation %d\n", ret);
+ goto err;
+ }
+
+ size = roundup(FSL_CAAM_MP_PUBK_BYTES, ARCH_DMA_MINALIGN);
+ invalidate_dcache_range((unsigned long)dst, (unsigned long)dst + size);
+err:
+ free(dsc);
+ return ret;
+}
+
+int sign_mppubk(const u8 *m, int data_size, u8 *dgst, u8 *c, u8 *d)
+{
+ int size, ret;
+ u32 *dsc;
+
+ /* Job Descriptor initialization */
+ dsc = memalign(ARCH_DMA_MINALIGN,
+ sizeof(uint32_t) * MFG_SIGN_DSC_WORDS);
+ if (!dsc) {
+ debug("Not enough memory for descriptor allocation\n");
+ return -ENOMEM;
+ }
+
+ mfg_build_sign_dsc(dsc, m, data_size, dgst, c, d);
+
+ size = roundup(sizeof(uint32_t) * MFG_SIGN_DSC_WORDS,
+ ARCH_DMA_MINALIGN);
+ flush_dcache_range((unsigned long)dsc, (unsigned long)dsc + size);
+
+ size = roundup(data_size, ARCH_DMA_MINALIGN);
+ flush_dcache_range((unsigned long)m, (unsigned long)m + size);
+
+ size = roundup(FSL_CAAM_MP_MES_DGST_BYTES, ARCH_DMA_MINALIGN);
+ flush_dcache_range((unsigned long)dgst, (unsigned long)dgst + size);
+
+ size = roundup(FSL_CAAM_MP_PRVK_BYTES, ARCH_DMA_MINALIGN);
+ flush_dcache_range((unsigned long)c, (unsigned long)c + size);
+ flush_dcache_range((unsigned long)d, (unsigned long)d + size);
+
+ /* Execute Job Descriptor */
+ puts("\nSigning message with Manufacturing Protection Private Key\n");
+
+ ret = run_descriptor_jr(dsc);
+ if (ret) {
+ debug("Error in public key generation %d\n", ret);
+ goto err;
+ }
+
+ size = roundup(FSL_CAAM_MP_MES_DGST_BYTES, ARCH_DMA_MINALIGN);
+ invalidate_dcache_range((unsigned long)dgst,
+ (unsigned long)dgst + size);
+
+ size = roundup(FSL_CAAM_MP_PRVK_BYTES, ARCH_DMA_MINALIGN);
+ invalidate_dcache_range((unsigned long)c, (unsigned long)c + size);
+ invalidate_dcache_range((unsigned long)d, (unsigned long)d + size);
+
+err:
+ free(dsc);
+ return ret;
+}
diff --git a/drivers/crypto/fsl/jobdesc.c b/drivers/crypto/fsl/jobdesc.c
index fbc1aeddeeb..d2354155318 100644
--- a/drivers/crypto/fsl/jobdesc.c
+++ b/drivers/crypto/fsl/jobdesc.c
@@ -4,6 +4,7 @@
* Basic job descriptor construction
*
* Copyright 2014 Freescale Semiconductor, Inc.
+ * Copyright 2018 NXP
*
*/
@@ -15,7 +16,8 @@
#include "rsa_caam.h"
#include <asm/cache.h>
-#if defined(CONFIG_MX6) || defined(CONFIG_MX7)
+#if defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_MX7ULP) || \
+ defined(CONFIG_IMX8M)
/*!
* Secure memory run command
*
@@ -163,9 +165,9 @@ int inline_cnstr_jobdesc_blob_dek(uint32_t *desc, const uint8_t *plain_txt,
append_u32(desc, aad_w2);
- append_cmd_ptr(desc, (dma_addr_t)SEC_MEM_PAGE1, in_sz, CMD_SEQ_IN_PTR);
+ append_cmd_ptr(desc, (caam_dma_addr_t)SEC_MEM_PAGE1, in_sz, CMD_SEQ_IN_PTR);
- append_cmd_ptr(desc, (dma_addr_t)dek_blob + 8, out_sz, CMD_SEQ_OUT_PTR);
+ append_cmd_ptr(desc, (caam_dma_addr_t)(ulong)(dek_blob + 8), out_sz, CMD_SEQ_OUT_PTR);
append_operation(desc, OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB |
OP_PCLID_SECMEM);
@@ -181,7 +183,7 @@ void inline_cnstr_jobdesc_hash(uint32_t *desc,
/* SHA 256 , output is of length 32 words */
uint32_t storelen = alg_size;
u32 options;
- dma_addr_t dma_addr_in, dma_addr_out;
+ caam_dma_addr_t dma_addr_in, dma_addr_out;
dma_addr_in = virt_to_phys((void *)msg);
dma_addr_out = virt_to_phys((void *)digest);
@@ -210,7 +212,7 @@ void inline_cnstr_jobdesc_blob_encap(uint32_t *desc, uint8_t *key_idnfr,
uint8_t *plain_txt, uint8_t *enc_blob,
uint32_t in_sz)
{
- dma_addr_t dma_addr_key_idnfr, dma_addr_in, dma_addr_out;
+ caam_dma_addr_t dma_addr_key_idnfr, dma_addr_in, dma_addr_out;
uint32_t key_sz = KEY_IDNFR_SZ_BYTES;
/* output blob will have 32 bytes key blob in beginning and
* 16 byte HMAC identifier at end of data blob */
@@ -235,7 +237,7 @@ void inline_cnstr_jobdesc_blob_decap(uint32_t *desc, uint8_t *key_idnfr,
uint8_t *enc_blob, uint8_t *plain_txt,
uint32_t out_sz)
{
- dma_addr_t dma_addr_key_idnfr, dma_addr_in, dma_addr_out;
+ caam_dma_addr_t dma_addr_key_idnfr, dma_addr_in, dma_addr_out;
uint32_t key_sz = KEY_IDNFR_SZ_BYTES;
uint32_t in_sz = out_sz + KEY_BLOB_SIZE + MAC_SIZE;
@@ -311,7 +313,7 @@ void inline_cnstr_jobdesc_pkha_rsaexp(uint32_t *desc,
struct pk_in_params *pkin, uint8_t *out,
uint32_t out_siz)
{
- dma_addr_t dma_addr_e, dma_addr_a, dma_addr_n, dma_addr_out;
+ caam_dma_addr_t dma_addr_e, dma_addr_a, dma_addr_n, dma_addr_out;
dma_addr_e = virt_to_phys((void *)pkin->e);
dma_addr_a = virt_to_phys((void *)pkin->a);
diff --git a/drivers/crypto/fsl/jr.c b/drivers/crypto/fsl/jr.c
index 44273c345f9..22b649219e8 100644
--- a/drivers/crypto/fsl/jr.c
+++ b/drivers/crypto/fsl/jr.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2008-2014 Freescale Semiconductor, Inc.
+ * Copyright 2018 NXP
*
* Based on CAAM driver in drivers/crypto/caam in Linux
*/
@@ -21,6 +22,7 @@
#include <asm/fsl_pamu.h>
#endif
#include <dm/lists.h>
+#include <linux/delay.h>
#define CIRC_CNT(head, tail, size) (((head) - (tail)) & (size - 1))
#define CIRC_SPACE(head, tail, size) CIRC_CNT((tail), (head) + 1, (size))
@@ -34,10 +36,10 @@ uint32_t sec_offset[CONFIG_SYS_FSL_MAX_NUM_OF_SEC] = {
};
#define SEC_ADDR(idx) \
- ((CONFIG_SYS_FSL_SEC_ADDR + sec_offset[idx]))
+ (ulong)((CONFIG_SYS_FSL_SEC_ADDR + sec_offset[idx]))
#define SEC_JR0_ADDR(idx) \
- (SEC_ADDR(idx) + \
+ (ulong)(SEC_ADDR(idx) + \
(CONFIG_SYS_FSL_JR0_OFFSET - CONFIG_SYS_FSL_SEC_OFFSET))
struct jobring jr0[CONFIG_SYS_FSL_MAX_NUM_OF_SEC];
@@ -82,16 +84,16 @@ static void jr_initregs(uint8_t sec_idx)
{
struct jr_regs *regs = (struct jr_regs *)SEC_JR0_ADDR(sec_idx);
struct jobring *jr = &jr0[sec_idx];
- phys_addr_t ip_base = virt_to_phys((void *)jr->input_ring);
- phys_addr_t op_base = virt_to_phys((void *)jr->output_ring);
+ caam_dma_addr_t ip_base = virt_to_phys((void *)jr->input_ring);
+ caam_dma_addr_t op_base = virt_to_phys((void *)jr->output_ring);
-#ifdef CONFIG_PHYS_64BIT
+#ifdef CONFIG_CAAM_64BIT
sec_out32(&regs->irba_h, ip_base >> 32);
#else
sec_out32(&regs->irba_h, 0x0);
#endif
sec_out32(&regs->irba_l, (uint32_t)ip_base);
-#ifdef CONFIG_PHYS_64BIT
+#ifdef CONFIG_CAAM_64BIT
sec_out32(&regs->orba_h, op_base >> 32);
#else
sec_out32(&regs->orba_h, 0x0);
@@ -117,8 +119,8 @@ static int jr_init(uint8_t sec_idx)
jr->liodn = DEFAULT_JR_LIODN;
#endif
jr->size = JR_SIZE;
- jr->input_ring = (dma_addr_t *)memalign(ARCH_DMA_MINALIGN,
- JR_SIZE * sizeof(dma_addr_t));
+ jr->input_ring = (caam_dma_addr_t *)memalign(ARCH_DMA_MINALIGN,
+ JR_SIZE * sizeof(caam_dma_addr_t));
if (!jr->input_ring)
return -1;
@@ -129,7 +131,7 @@ static int jr_init(uint8_t sec_idx)
if (!jr->output_ring)
return -1;
- memset(jr->input_ring, 0, JR_SIZE * sizeof(dma_addr_t));
+ memset(jr->input_ring, 0, JR_SIZE * sizeof(caam_dma_addr_t));
memset(jr->output_ring, 0, jr->op_size);
start_jr0(sec_idx);
@@ -148,7 +150,7 @@ static int jr_sw_cleanup(uint8_t sec_idx)
jr->read_idx = 0;
jr->write_idx = 0;
memset(jr->info, 0, sizeof(jr->info));
- memset(jr->input_ring, 0, jr->size * sizeof(dma_addr_t));
+ memset(jr->input_ring, 0, jr->size * sizeof(caam_dma_addr_t));
memset(jr->output_ring, 0, jr->size * sizeof(struct op_ring));
return 0;
@@ -194,7 +196,7 @@ static int jr_enqueue(uint32_t *desc_addr,
uint32_t desc_word;
int length = desc_len(desc_addr);
int i;
-#ifdef CONFIG_PHYS_64BIT
+#ifdef CONFIG_CAAM_64BIT
uint32_t *addr_hi, *addr_lo;
#endif
@@ -208,7 +210,7 @@ static int jr_enqueue(uint32_t *desc_addr,
sec_out32((uint32_t *)&desc_addr[i], desc_word);
}
- phys_addr_t desc_phys_addr = virt_to_phys(desc_addr);
+ caam_dma_addr_t desc_phys_addr = virt_to_phys(desc_addr);
jr->info[head].desc_phys_addr = desc_phys_addr;
jr->info[head].callback = (void *)callback;
@@ -221,7 +223,7 @@ static int jr_enqueue(uint32_t *desc_addr,
sizeof(struct jr_info), ARCH_DMA_MINALIGN);
flush_dcache_range(start, end);
-#ifdef CONFIG_PHYS_64BIT
+#ifdef CONFIG_CAAM_64BIT
/* Write the 64 bit Descriptor address on Input Ring.
* The 32 bit hign and low part of the address will
* depend on endianness of SEC block.
@@ -240,11 +242,11 @@ static int jr_enqueue(uint32_t *desc_addr,
#else
/* Write the 32 bit Descriptor address on Input Ring. */
sec_out32(&jr->input_ring[head], desc_phys_addr);
-#endif /* ifdef CONFIG_PHYS_64BIT */
+#endif /* ifdef CONFIG_CAAM_64BIT */
start = (unsigned long)&jr->input_ring[head] & ~(ARCH_DMA_MINALIGN - 1);
end = ALIGN((unsigned long)&jr->input_ring[head] +
- sizeof(dma_addr_t), ARCH_DMA_MINALIGN);
+ sizeof(caam_dma_addr_t), ARCH_DMA_MINALIGN);
flush_dcache_range(start, end);
jr->head = (head + 1) & (jr->size - 1);
@@ -270,7 +272,7 @@ static int jr_dequeue(int sec_idx)
int idx, i, found;
void (*callback)(uint32_t status, void *arg);
void *arg = NULL;
-#ifdef CONFIG_PHYS_64BIT
+#ifdef CONFIG_CAAM_64BIT
uint32_t *addr_hi, *addr_lo;
#else
uint32_t *addr;
@@ -281,8 +283,8 @@ static int jr_dequeue(int sec_idx)
found = 0;
- phys_addr_t op_desc;
- #ifdef CONFIG_PHYS_64BIT
+ caam_dma_addr_t op_desc;
+ #ifdef CONFIG_CAAM_64BIT
/* Read the 64 bit Descriptor address from Output Ring.
* The 32 bit hign and low part of the address will
* depend on endianness of SEC block.
@@ -302,7 +304,7 @@ static int jr_dequeue(int sec_idx)
/* Read the 32 bit Descriptor address from Output Ring. */
addr = (uint32_t *)&jr->output_ring[jr->tail].desc;
op_desc = sec_in32(addr);
- #endif /* ifdef CONFIG_PHYS_64BIT */
+ #endif /* ifdef CONFIG_CAAM_64BIT */
uint32_t status = sec_in32(&jr->output_ring[jr->tail].status);
@@ -355,8 +357,8 @@ static void desc_done(uint32_t status, void *arg)
static inline int run_descriptor_jr_idx(uint32_t *desc, uint8_t sec_idx)
{
- unsigned long long timeval = get_ticks();
- unsigned long long timeout = usec2ticks(CONFIG_SEC_DEQ_TIMEOUT);
+ unsigned long long timeval = 0;
+ unsigned long long timeout = CONFIG_USEC_DEQ_TIMEOUT;
struct result op;
int ret = 0;
@@ -369,9 +371,10 @@ static inline int run_descriptor_jr_idx(uint32_t *desc, uint8_t sec_idx)
goto out;
}
- timeval = get_ticks();
- timeout = usec2ticks(CONFIG_SEC_DEQ_TIMEOUT);
while (op.done != 1) {
+ udelay(1);
+ timeval += 1;
+
ret = jr_dequeue(sec_idx);
if (ret) {
debug("Error in SEC deq\n");
@@ -379,7 +382,7 @@ static inline int run_descriptor_jr_idx(uint32_t *desc, uint8_t sec_idx)
goto out;
}
- if ((get_ticks() - timeval) > timeout) {
+ if (timeval > timeout) {
debug("SEC Dequeue timed out\n");
ret = JQ_DEQ_TO_ERR;
goto out;
@@ -675,7 +678,7 @@ int sec_init_idx(uint8_t sec_idx)
mcr = (mcr & ~MCFGR_AWCACHE_MASK) | (0x2 << MCFGR_AWCACHE_SHIFT);
#endif
-#ifdef CONFIG_PHYS_64BIT
+#ifdef CONFIG_CAAM_64BIT
mcr |= (1 << MCFGR_PS_SHIFT);
#endif
sec_out32(&sec->mcfgr, mcr);
diff --git a/drivers/crypto/fsl/jr.h b/drivers/crypto/fsl/jr.h
index ffd3a192738..1047aa772c4 100644
--- a/drivers/crypto/fsl/jr.h
+++ b/drivers/crypto/fsl/jr.h
@@ -8,10 +8,11 @@
#define __JR_H
#include <linux/compiler.h>
+#include "type.h"
#define JR_SIZE 4
-/* Timeout currently defined as 90 sec */
-#define CONFIG_SEC_DEQ_TIMEOUT 90000000U
+/* Timeout currently defined as 10 sec */
+#define CONFIG_USEC_DEQ_TIMEOUT 10000000U
#define DEFAULT_JR_ID 0
#define DEFAULT_JR_LIODN 0
@@ -41,13 +42,13 @@
#define RNG4_MAX_HANDLES 2
struct op_ring {
- phys_addr_t desc;
+ caam_dma_addr_t desc;
uint32_t status;
} __packed;
struct jr_info {
void (*callback)(uint32_t status, void *arg);
- phys_addr_t desc_phys_addr;
+ caam_dma_addr_t desc_phys_addr;
uint32_t desc_len;
uint32_t op_done;
void *arg;
@@ -83,7 +84,7 @@ struct jobring {
* by SEC
*/
/*Circular Ring of i/p descriptors */
- dma_addr_t *input_ring;
+ caam_dma_addr_t *input_ring;
/* Circular Ring of o/p descriptors */
/* Circula Ring containing info regarding descriptors in i/p
* and o/p ring
diff --git a/drivers/crypto/fsl/type.h b/drivers/crypto/fsl/type.h
new file mode 100644
index 00000000000..b7031a60fdd
--- /dev/null
+++ b/drivers/crypto/fsl/type.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2020 NXP
+ *
+ */
+
+#ifndef CRYPTO_FSL_TYPE_H
+#define CRYPTO_FSL_TYPE_H
+
+#ifdef CONFIG_CAAM_64BIT
+typedef unsigned long long caam_dma_addr_t;
+#else
+typedef u32 caam_dma_addr_t;
+#endif
+
+#endif
diff --git a/drivers/ddr/imx/imx8m/Kconfig b/drivers/ddr/imx/imx8m/Kconfig
index a5f5524fbec..a90b7db4940 100644
--- a/drivers/ddr/imx/imx8m/Kconfig
+++ b/drivers/ddr/imx/imx8m/Kconfig
@@ -36,4 +36,12 @@ config IMX8M_DRAM_INLINE_ECC
help
Select this config if you want to use inline ecc feature for
imx8mp-evk board.
+
+config IMX8M_VDD_SOC_850MV
+ bool "imx8mp change the vdd_soc voltage to 850mv"
+ depends on IMX8MP
+
+config IMX8M_LPDDR4_FREQ0_2400MTS
+ bool "imx8m PDDR4 freq0 change from 4000MTS to 2400MTS"
+
endmenu
diff --git a/drivers/misc/mxc_ocotp.c b/drivers/misc/mxc_ocotp.c
index 926c62c8a14..b1893a5c7eb 100644
--- a/drivers/misc/mxc_ocotp.c
+++ b/drivers/misc/mxc_ocotp.c
@@ -335,7 +335,7 @@ int fuse_sense(u32 bank, u32 word, u32 *val)
struct ocotp_regs *regs;
int ret;
- if (is_imx8mq() && is_soc_rev(CHIP_REV_2_1)) {
+ if (is_imx8mq() && (soc_rev() >= CHIP_REV_2_1)) {
printf("mxc_ocotp %s(): fuse sense is disabled\n", __func__);
return -EPERM;
}
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 492567575ec..197aa82040d 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -327,6 +327,15 @@ config MMC_OCTEONTX
If unsure, say N.
+config MVEBU_MMC
+ bool "Kirkwood MMC controller support"
+ depends on DM_MMC && BLK && ARCH_KIRKWOOD
+ help
+ Support for MMC host controller on Kirkwood SoCs.
+ If you are on a Kirkwood architecture, say Y here.
+
+ If unsure, say N.
+
config PXA_MMC_GENERIC
bool "Support for MMC controllers on PXA"
help
diff --git a/drivers/mmc/fsl_esdhc_imx.c b/drivers/mmc/fsl_esdhc_imx.c
index 09a5cd61e3b..a4675838e58 100644
--- a/drivers/mmc/fsl_esdhc_imx.c
+++ b/drivers/mmc/fsl_esdhc_imx.c
@@ -146,6 +146,7 @@ struct esdhc_soc_data {
* @start_tuning_tap: the start point for tuning in tuning_ctrl register
* @strobe_dll_delay_target: settings in strobe_dllctrl
* @signal_voltage: indicating the current voltage
+ * @signal_voltage_switch_extra_delay_ms: extra delay for IO voltage switch
* @cd_gpio: gpio for card detection
* @wp_gpio: gpio for write protection
*/
@@ -170,6 +171,7 @@ struct fsl_esdhc_priv {
u32 tuning_start_tap;
u32 strobe_dll_delay_target;
u32 signal_voltage;
+ u32 signal_voltage_switch_extra_delay_ms;
#if CONFIG_IS_ENABLED(DM_REGULATOR)
struct udevice *vqmmc_dev;
struct udevice *vmmc_dev;
@@ -521,15 +523,6 @@ static int esdhc_send_cmd_common(struct fsl_esdhc_priv *priv, struct mmc *mmc,
goto out;
}
- /* Switch voltage to 1.8V if CMD11 succeeded */
- if (cmd->cmdidx == SD_CMD_SWITCH_UHS18V) {
- esdhc_setbits32(&regs->vendorspec, ESDHC_VENDORSPEC_VSELECT);
-
- printf("Run CMD11 1.8V switch\n");
- /* Sleep for 5 ms - max time for card to switch to 1.8V */
- udelay(5000);
- }
-
/* Workaround for ESDHC errata ENGcm03648 */
if (!data && (cmd->resp_type & MMC_RSP_BUSY)) {
int timeout = 50000;
@@ -660,7 +653,10 @@ static void set_sysctl(struct fsl_esdhc_priv *priv, struct mmc *mmc, uint clock)
clk = (pre_div << 8) | (div << 4);
#ifdef CONFIG_FSL_USDHC
- esdhc_clrbits32(&regs->vendorspec, VENDORSPEC_CKEN);
+ esdhc_clrbits32(&regs->vendorspec, VENDORSPEC_FRC_SDCLK_ON);
+ ret = readx_poll_timeout(esdhc_read32, &regs->prsstat, tmp, tmp & PRSSTAT_SDOFF, 100);
+ if (ret)
+ pr_warn("fsl_esdhc_imx: Internal clock never gate off.\n");
#else
esdhc_clrbits32(&regs->sysctl, SYSCTL_CKEN);
#endif
@@ -672,7 +668,7 @@ static void set_sysctl(struct fsl_esdhc_priv *priv, struct mmc *mmc, uint clock)
pr_warn("fsl_esdhc_imx: Internal clock never stabilised.\n");
#ifdef CONFIG_FSL_USDHC
- esdhc_setbits32(&regs->vendorspec, VENDORSPEC_PEREN | VENDORSPEC_CKEN);
+ esdhc_setbits32(&regs->vendorspec, VENDORSPEC_FRC_SDCLK_ON);
#else
esdhc_setbits32(&regs->sysctl, SYSCTL_PEREN | SYSCTL_CKEN);
#endif
@@ -727,8 +723,14 @@ static void esdhc_set_strobe_dll(struct mmc *mmc)
struct fsl_esdhc_priv *priv = dev_get_priv(mmc->dev);
struct fsl_esdhc *regs = priv->esdhc_regs;
u32 val;
+ u32 tmp;
+ int ret;
if (priv->clock > ESDHC_STROBE_DLL_CLK_FREQ) {
+ esdhc_clrbits32(&regs->vendorspec, VENDORSPEC_FRC_SDCLK_ON);
+ ret = readx_poll_timeout(esdhc_read32, &regs->prsstat, tmp, tmp & PRSSTAT_SDOFF, 100);
+ if (ret)
+ pr_warn("fsl_esdhc_imx: Internal clock never gate off.\n");
esdhc_write32(&regs->strobe_dllctrl, ESDHC_STROBE_DLL_CTRL_RESET);
/*
@@ -746,6 +748,7 @@ static void esdhc_set_strobe_dll(struct mmc *mmc)
pr_warn("HS400 strobe DLL status REF not lock!\n");
if (!(val & ESDHC_STROBE_DLL_STS_SLV_LOCK))
pr_warn("HS400 strobe DLL status SLV not lock!\n");
+ esdhc_setbits32(&regs->vendorspec, VENDORSPEC_FRC_SDCLK_ON);
}
}
@@ -835,6 +838,14 @@ static int esdhc_set_voltage(struct mmc *mmc)
}
#endif
esdhc_setbits32(&regs->vendorspec, ESDHC_VENDORSPEC_VSELECT);
+ /*
+ * some board like imx8mm-evk need about 18ms to switch
+ * the IO voltage from 3.3v to 1.8v, common code only
+ * delay 10ms, so need to delay extra time to make sure
+ * the IO voltage change to 1.8v.
+ */
+ if (priv->signal_voltage_switch_extra_delay_ms)
+ mdelay(priv->signal_voltage_switch_extra_delay_ms);
if (esdhc_read32(&regs->vendorspec) & ESDHC_VENDORSPEC_VSELECT)
return 0;
@@ -969,14 +980,18 @@ static int esdhc_set_ios_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
#ifdef MMC_SUPPORTS_TUNING
if (mmc->clk_disable) {
#ifdef CONFIG_FSL_USDHC
- esdhc_clrbits32(&regs->vendorspec, VENDORSPEC_CKEN);
+ u32 tmp;
+
+ esdhc_clrbits32(&regs->vendorspec, VENDORSPEC_FRC_SDCLK_ON);
+ ret = readx_poll_timeout(esdhc_read32, &regs->prsstat, tmp, tmp & PRSSTAT_SDOFF, 100);
+ if (ret)
+ pr_warn("fsl_esdhc_imx: Internal clock never gate off.\n");
#else
esdhc_clrbits32(&regs->sysctl, SYSCTL_CKEN);
#endif
} else {
#ifdef CONFIG_FSL_USDHC
- esdhc_setbits32(&regs->vendorspec, VENDORSPEC_PEREN |
- VENDORSPEC_CKEN);
+ esdhc_setbits32(&regs->vendorspec, VENDORSPEC_FRC_SDCLK_ON);
#else
esdhc_setbits32(&regs->sysctl, SYSCTL_PEREN | SYSCTL_CKEN);
#endif
@@ -1052,7 +1067,7 @@ static int esdhc_init_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
#ifndef CONFIG_FSL_USDHC
esdhc_setbits32(&regs->sysctl, SYSCTL_HCKEN | SYSCTL_IPGEN);
#else
- esdhc_setbits32(&regs->vendorspec, VENDORSPEC_HCKEN | VENDORSPEC_IPGEN);
+ esdhc_setbits32(&regs->vendorspec, VENDORSPEC_FRC_SDCLK_ON);
#endif
/* Set the initial clock speed */
@@ -1190,8 +1205,7 @@ static int fsl_esdhc_init(struct fsl_esdhc_priv *priv,
esdhc_write32(&regs->autoc12err, 0);
esdhc_write32(&regs->clktunectrlstatus, 0);
#else
- esdhc_setbits32(&regs->vendorspec, VENDORSPEC_PEREN |
- VENDORSPEC_HCKEN | VENDORSPEC_IPGEN | VENDORSPEC_CKEN);
+ esdhc_setbits32(&regs->vendorspec, VENDORSPEC_FRC_SDCLK_ON);
#endif
if (priv->vs18_enable)
@@ -1446,6 +1460,8 @@ static int fsl_esdhc_of_to_plat(struct udevice *dev)
val = fdtdec_get_int(fdt, node, "fsl,strobe-dll-delay-target",
ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_DEFAULT);
priv->strobe_dll_delay_target = val;
+ val = fdtdec_get_int(fdt, node, "fsl,signal-voltage-switch-extra-delay-ms", 0);
+ priv->signal_voltage_switch_extra_delay_ms = val;
if (dev_read_bool(dev, "broken-cd"))
priv->broken_cd = 1;
diff --git a/drivers/mmc/mvebu_mmc.c b/drivers/mmc/mvebu_mmc.c
index 8ec1f57a1b7..fea55c61ed7 100644
--- a/drivers/mmc/mvebu_mmc.c
+++ b/drivers/mmc/mvebu_mmc.c
@@ -11,60 +11,67 @@
#include <errno.h>
#include <log.h>
#include <malloc.h>
+#include <dm.h>
+#include <fdtdec.h>
#include <part.h>
#include <mmc.h>
-#include <asm/global_data.h>
#include <asm/io.h>
#include <asm/arch/cpu.h>
#include <asm/arch/soc.h>
#include <mvebu_mmc.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-#define DRIVER_NAME "MVEBU_MMC"
+#include <dm/device_compat.h>
#define MVEBU_TARGET_DRAM 0
#define TIMEOUT_DELAY 5*CONFIG_SYS_HZ /* wait 5 seconds */
-static void mvebu_mmc_write(u32 offs, u32 val)
+static inline void *get_regbase(const struct mmc *mmc)
{
- writel(val, CONFIG_SYS_MMC_BASE + (offs));
+ struct mvebu_mmc_plat *pdata = mmc->priv;
+
+ return pdata->iobase;
}
-static u32 mvebu_mmc_read(u32 offs)
+static void mvebu_mmc_write(const struct mmc *mmc, u32 offs, u32 val)
{
- return readl(CONFIG_SYS_MMC_BASE + (offs));
+ writel(val, get_regbase(mmc) + (offs));
}
-static int mvebu_mmc_setup_data(struct mmc_data *data)
+static u32 mvebu_mmc_read(const struct mmc *mmc, u32 offs)
{
+ return readl(get_regbase(mmc) + (offs));
+}
+
+static int mvebu_mmc_setup_data(struct udevice *dev, struct mmc_data *data)
+{
+ struct mvebu_mmc_plat *pdata = dev_get_plat(dev);
+ struct mmc *mmc = &pdata->mmc;
u32 ctrl_reg;
- debug("%s, data %s : blocks=%d blksz=%d\n", DRIVER_NAME,
- (data->flags & MMC_DATA_READ) ? "read" : "write",
- data->blocks, data->blocksize);
+ dev_dbg(dev, "data %s : blocks=%d blksz=%d\n",
+ (data->flags & MMC_DATA_READ) ? "read" : "write",
+ data->blocks, data->blocksize);
/* default to maximum timeout */
- ctrl_reg = mvebu_mmc_read(SDIO_HOST_CTRL);
+ ctrl_reg = mvebu_mmc_read(mmc, SDIO_HOST_CTRL);
ctrl_reg |= SDIO_HOST_CTRL_TMOUT(SDIO_HOST_CTRL_TMOUT_MAX);
- mvebu_mmc_write(SDIO_HOST_CTRL, ctrl_reg);
+ mvebu_mmc_write(mmc, SDIO_HOST_CTRL, ctrl_reg);
if (data->flags & MMC_DATA_READ) {
- mvebu_mmc_write(SDIO_SYS_ADDR_LOW, (u32)data->dest & 0xffff);
- mvebu_mmc_write(SDIO_SYS_ADDR_HI, (u32)data->dest >> 16);
+ mvebu_mmc_write(mmc, SDIO_SYS_ADDR_LOW, (u32)data->dest & 0xffff);
+ mvebu_mmc_write(mmc, SDIO_SYS_ADDR_HI, (u32)data->dest >> 16);
} else {
- mvebu_mmc_write(SDIO_SYS_ADDR_LOW, (u32)data->src & 0xffff);
- mvebu_mmc_write(SDIO_SYS_ADDR_HI, (u32)data->src >> 16);
+ mvebu_mmc_write(mmc, SDIO_SYS_ADDR_LOW, (u32)data->src & 0xffff);
+ mvebu_mmc_write(mmc, SDIO_SYS_ADDR_HI, (u32)data->src >> 16);
}
- mvebu_mmc_write(SDIO_BLK_COUNT, data->blocks);
- mvebu_mmc_write(SDIO_BLK_SIZE, data->blocksize);
+ mvebu_mmc_write(mmc, SDIO_BLK_COUNT, data->blocks);
+ mvebu_mmc_write(mmc, SDIO_BLK_SIZE, data->blocksize);
return 0;
}
-static int mvebu_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
+static int mvebu_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
struct mmc_data *data)
{
ulong start;
@@ -72,12 +79,14 @@ static int mvebu_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
ushort resptype = 0;
ushort xfertype = 0;
ushort resp_indx = 0;
+ struct mvebu_mmc_plat *pdata = dev_get_plat(dev);
+ struct mmc *mmc = &pdata->mmc;
- debug("%s: cmdidx [0x%x] resp_type[0x%x] cmdarg[0x%x]\n",
- DRIVER_NAME, cmd->cmdidx, cmd->resp_type, cmd->cmdarg);
+ dev_dbg(dev, "cmdidx [0x%x] resp_type[0x%x] cmdarg[0x%x]\n",
+ cmd->cmdidx, cmd->resp_type, cmd->cmdarg);
- debug("%s: cmd %d (hw state 0x%04x)\n", DRIVER_NAME,
- cmd->cmdidx, mvebu_mmc_read(SDIO_HW_STATE));
+ dev_dbg(dev, "cmd %d (hw state 0x%04x)\n",
+ cmd->cmdidx, mvebu_mmc_read(mmc, SDIO_HW_STATE));
/*
* Hardware weirdness. The FIFO_EMPTY bit of the HW_STATE
@@ -88,26 +97,26 @@ static int mvebu_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
* this bit comes to good sense (which eventually happens by
* itself) then the new transfer simply fails with a timeout.
*/
- if (!(mvebu_mmc_read(SDIO_HW_STATE) & CMD_FIFO_EMPTY)) {
+ if (!(mvebu_mmc_read(mmc, SDIO_HW_STATE) & CMD_FIFO_EMPTY)) {
ushort hw_state, count = 0;
start = get_timer(0);
do {
- hw_state = mvebu_mmc_read(SDIO_HW_STATE);
+ hw_state = mvebu_mmc_read(mmc, SDIO_HW_STATE);
if ((get_timer(0) - start) > TIMEOUT_DELAY) {
printf("%s : FIFO_EMPTY bit missing\n",
- DRIVER_NAME);
+ dev->name);
break;
}
count++;
} while (!(hw_state & CMD_FIFO_EMPTY));
- debug("%s *** wait for FIFO_EMPTY bit (hw=0x%04x, count=%d, jiffies=%ld)\n",
- DRIVER_NAME, hw_state, count, (get_timer(0) - (start)));
+ dev_dbg(dev, "*** wait for FIFO_EMPTY bit (hw=0x%04x, count=%d, jiffies=%ld)\n",
+ hw_state, count, (get_timer(0) - (start)));
}
/* Clear status */
- mvebu_mmc_write(SDIO_NOR_INTR_STATUS, SDIO_POLL_MASK);
- mvebu_mmc_write(SDIO_ERR_INTR_STATUS, SDIO_POLL_MASK);
+ mvebu_mmc_write(mmc, SDIO_NOR_INTR_STATUS, SDIO_POLL_MASK);
+ mvebu_mmc_write(mmc, SDIO_ERR_INTR_STATUS, SDIO_POLL_MASK);
resptype = SDIO_CMD_INDEX(cmd->cmdidx);
@@ -133,11 +142,10 @@ static int mvebu_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
}
if (data) {
- int err = mvebu_mmc_setup_data(data);
+ int err = mvebu_mmc_setup_data(dev, data);
if (err) {
- debug("%s: command DATA error :%x\n",
- DRIVER_NAME, err);
+ dev_dbg(dev, "command DATA error :%x\n", err);
return err;
}
@@ -154,34 +162,33 @@ static int mvebu_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
}
/* Setting cmd arguments */
- mvebu_mmc_write(SDIO_ARG_LOW, cmd->cmdarg & 0xffff);
- mvebu_mmc_write(SDIO_ARG_HI, cmd->cmdarg >> 16);
+ mvebu_mmc_write(mmc, SDIO_ARG_LOW, cmd->cmdarg & 0xffff);
+ mvebu_mmc_write(mmc, SDIO_ARG_HI, cmd->cmdarg >> 16);
/* Setting Xfer mode */
- mvebu_mmc_write(SDIO_XFER_MODE, xfertype);
+ mvebu_mmc_write(mmc, SDIO_XFER_MODE, xfertype);
/* Sending command */
- mvebu_mmc_write(SDIO_CMD, resptype);
+ mvebu_mmc_write(mmc, SDIO_CMD, resptype);
start = get_timer(0);
- while (!((mvebu_mmc_read(SDIO_NOR_INTR_STATUS)) & waittype)) {
- if (mvebu_mmc_read(SDIO_NOR_INTR_STATUS) & SDIO_NOR_ERROR) {
- debug("%s: error! cmdidx : %d, err reg: %04x\n",
- DRIVER_NAME, cmd->cmdidx,
- mvebu_mmc_read(SDIO_ERR_INTR_STATUS));
- if (mvebu_mmc_read(SDIO_ERR_INTR_STATUS) &
+ while (!((mvebu_mmc_read(mmc, SDIO_NOR_INTR_STATUS)) & waittype)) {
+ if (mvebu_mmc_read(mmc, SDIO_NOR_INTR_STATUS) & SDIO_NOR_ERROR) {
+ dev_dbg(dev, "error! cmdidx : %d, err reg: %04x\n",
+ cmd->cmdidx,
+ mvebu_mmc_read(mmc, SDIO_ERR_INTR_STATUS));
+ if (mvebu_mmc_read(mmc, SDIO_ERR_INTR_STATUS) &
(SDIO_ERR_CMD_TIMEOUT | SDIO_ERR_DATA_TIMEOUT)) {
- debug("%s: command READ timed out\n",
- DRIVER_NAME);
+ dev_dbg(dev, "command READ timed out\n");
return -ETIMEDOUT;
}
- debug("%s: command READ error\n", DRIVER_NAME);
+ dev_dbg(dev, "command READ error\n");
return -ECOMM;
}
if ((get_timer(0) - start) > TIMEOUT_DELAY) {
- debug("%s: command timed out\n", DRIVER_NAME);
+ dev_dbg(dev, "command timed out\n");
return -ETIMEDOUT;
}
}
@@ -191,8 +198,7 @@ static int mvebu_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
uint response[8];
for (resp_indx = 0; resp_indx < 8; resp_indx++)
- response[resp_indx]
- = mvebu_mmc_read(SDIO_RSP(resp_indx));
+ response[resp_indx] = mvebu_mmc_read(mmc, SDIO_RSP(resp_indx));
cmd->response[0] = ((response[0] & 0x03ff) << 22) |
((response[1] & 0xffff) << 6) |
@@ -209,8 +215,7 @@ static int mvebu_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
uint response[3];
for (resp_indx = 0; resp_indx < 3; resp_indx++)
- response[resp_indx]
- = mvebu_mmc_read(SDIO_RSP(resp_indx));
+ response[resp_indx] = mvebu_mmc_read(mmc, SDIO_RSP(resp_indx));
cmd->response[0] = ((response[2] & 0x003f) << (8 - 8)) |
((response[1] & 0xffff) << (14 - 8)) |
@@ -225,64 +230,71 @@ static int mvebu_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
cmd->response[3] = 0;
}
- debug("%s: resp[0x%x] ", DRIVER_NAME, cmd->resp_type);
+ dev_dbg(dev, "resp[0x%x] ", cmd->resp_type);
debug("[0x%x] ", cmd->response[0]);
debug("[0x%x] ", cmd->response[1]);
debug("[0x%x] ", cmd->response[2]);
debug("[0x%x] ", cmd->response[3]);
debug("\n");
- if (mvebu_mmc_read(SDIO_ERR_INTR_STATUS) &
+ if (mvebu_mmc_read(mmc, SDIO_ERR_INTR_STATUS) &
(SDIO_ERR_CMD_TIMEOUT | SDIO_ERR_DATA_TIMEOUT))
return -ETIMEDOUT;
return 0;
}
-static void mvebu_mmc_power_up(void)
+static void mvebu_mmc_power_up(struct udevice *dev)
{
- debug("%s: power up\n", DRIVER_NAME);
+ struct mvebu_mmc_plat *pdata = dev_get_plat(dev);
+ struct mmc *mmc = &pdata->mmc;
+
+ dev_dbg(dev, "power up\n");
/* disable interrupts */
- mvebu_mmc_write(SDIO_NOR_INTR_EN, 0);
- mvebu_mmc_write(SDIO_ERR_INTR_EN, 0);
+ mvebu_mmc_write(mmc, SDIO_NOR_INTR_EN, 0);
+ mvebu_mmc_write(mmc, SDIO_ERR_INTR_EN, 0);
/* SW reset */
- mvebu_mmc_write(SDIO_SW_RESET, SDIO_SW_RESET_NOW);
+ mvebu_mmc_write(mmc, SDIO_SW_RESET, SDIO_SW_RESET_NOW);
- mvebu_mmc_write(SDIO_XFER_MODE, 0);
+ mvebu_mmc_write(mmc, SDIO_XFER_MODE, 0);
/* enable status */
- mvebu_mmc_write(SDIO_NOR_STATUS_EN, SDIO_POLL_MASK);
- mvebu_mmc_write(SDIO_ERR_STATUS_EN, SDIO_POLL_MASK);
+ mvebu_mmc_write(mmc, SDIO_NOR_STATUS_EN, SDIO_POLL_MASK);
+ mvebu_mmc_write(mmc, SDIO_ERR_STATUS_EN, SDIO_POLL_MASK);
/* enable interrupts status */
- mvebu_mmc_write(SDIO_NOR_INTR_STATUS, SDIO_POLL_MASK);
- mvebu_mmc_write(SDIO_ERR_INTR_STATUS, SDIO_POLL_MASK);
+ mvebu_mmc_write(mmc, SDIO_NOR_INTR_STATUS, SDIO_POLL_MASK);
+ mvebu_mmc_write(mmc, SDIO_ERR_INTR_STATUS, SDIO_POLL_MASK);
}
-static void mvebu_mmc_set_clk(unsigned int clock)
+static void mvebu_mmc_set_clk(struct udevice *dev, unsigned int clock)
{
unsigned int m;
+ struct mvebu_mmc_plat *pdata = dev_get_plat(dev);
+ struct mmc *mmc = &pdata->mmc;
if (clock == 0) {
- debug("%s: clock off\n", DRIVER_NAME);
- mvebu_mmc_write(SDIO_XFER_MODE, SDIO_XFER_MODE_STOP_CLK);
- mvebu_mmc_write(SDIO_CLK_DIV, MVEBU_MMC_BASE_DIV_MAX);
+ dev_dbg(dev, "clock off\n");
+ mvebu_mmc_write(mmc, SDIO_XFER_MODE, SDIO_XFER_MODE_STOP_CLK);
+ mvebu_mmc_write(mmc, SDIO_CLK_DIV, MVEBU_MMC_BASE_DIV_MAX);
} else {
m = MVEBU_MMC_BASE_FAST_CLOCK/(2*clock) - 1;
if (m > MVEBU_MMC_BASE_DIV_MAX)
m = MVEBU_MMC_BASE_DIV_MAX;
- mvebu_mmc_write(SDIO_CLK_DIV, m & MVEBU_MMC_BASE_DIV_MAX);
- debug("%s: clock (%d) div : %d\n", DRIVER_NAME, clock, m);
+ mvebu_mmc_write(mmc, SDIO_CLK_DIV, m & MVEBU_MMC_BASE_DIV_MAX);
+ dev_dbg(dev, "clock (%d) div : %d\n", clock, m);
}
}
-static void mvebu_mmc_set_bus(unsigned int bus)
+static void mvebu_mmc_set_bus(struct udevice *dev, unsigned int bus)
{
+ struct mvebu_mmc_plat *pdata = dev_get_plat(dev);
+ struct mmc *mmc = &pdata->mmc;
u32 ctrl_reg = 0;
- ctrl_reg = mvebu_mmc_read(SDIO_HOST_CTRL);
+ ctrl_reg = mvebu_mmc_read(mmc, SDIO_HOST_CTRL);
ctrl_reg &= ~SDIO_HOST_CTRL_DATA_WIDTH_4_BITS;
switch (bus) {
@@ -306,23 +318,26 @@ static void mvebu_mmc_set_bus(unsigned int bus)
ctrl_reg |= SDIO_HOST_CTRL_CARD_TYPE_MEM_ONLY;
- debug("%s: ctrl 0x%04x: %s %s %s\n", DRIVER_NAME, ctrl_reg,
- (ctrl_reg & SDIO_HOST_CTRL_PUSH_PULL_EN) ?
- "push-pull" : "open-drain",
- (ctrl_reg & SDIO_HOST_CTRL_DATA_WIDTH_4_BITS) ?
- "4bit-width" : "1bit-width",
- (ctrl_reg & SDIO_HOST_CTRL_HI_SPEED_EN) ?
- "high-speed" : "");
+ dev_dbg(dev, "ctrl 0x%04x: %s %s %s\n", ctrl_reg,
+ (ctrl_reg & SDIO_HOST_CTRL_PUSH_PULL_EN) ?
+ "push-pull" : "open-drain",
+ (ctrl_reg & SDIO_HOST_CTRL_DATA_WIDTH_4_BITS) ?
+ "4bit-width" : "1bit-width",
+ (ctrl_reg & SDIO_HOST_CTRL_HI_SPEED_EN) ?
+ "high-speed" : "");
- mvebu_mmc_write(SDIO_HOST_CTRL, ctrl_reg);
+ mvebu_mmc_write(mmc, SDIO_HOST_CTRL, ctrl_reg);
}
-static int mvebu_mmc_set_ios(struct mmc *mmc)
+static int mvebu_mmc_set_ios(struct udevice *dev)
{
- debug("%s: bus[%d] clock[%d]\n", DRIVER_NAME,
- mmc->bus_width, mmc->clock);
- mvebu_mmc_set_bus(mmc->bus_width);
- mvebu_mmc_set_clk(mmc->clock);
+ struct mvebu_mmc_plat *pdata = dev_get_plat(dev);
+ struct mmc *mmc = &pdata->mmc;
+
+ dev_dbg(dev, "bus[%d] clock[%d]\n",
+ mmc->bus_width, mmc->clock);
+ mvebu_mmc_set_bus(dev, mmc->bus_width);
+ mvebu_mmc_set_clk(dev, mmc->clock);
return 0;
}
@@ -330,13 +345,13 @@ static int mvebu_mmc_set_ios(struct mmc *mmc)
/*
* Set window register.
*/
-static void mvebu_window_setup(void)
+static void mvebu_window_setup(const struct mmc *mmc)
{
int i;
for (i = 0; i < 4; i++) {
- mvebu_mmc_write(WINDOW_CTRL(i), 0);
- mvebu_mmc_write(WINDOW_BASE(i), 0);
+ mvebu_mmc_write(mmc, WINDOW_CTRL(i), 0);
+ mvebu_mmc_write(mmc, WINDOW_BASE(i), 0);
}
for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
u32 size, base, attrib;
@@ -364,79 +379,119 @@ static void mvebu_window_setup(void)
size = gd->bd->bi_dram[i].size;
base = gd->bd->bi_dram[i].start;
if (size && attrib) {
- mvebu_mmc_write(WINDOW_CTRL(i),
+ mvebu_mmc_write(mmc, WINDOW_CTRL(i),
MVCPU_WIN_CTRL_DATA(size,
MVEBU_TARGET_DRAM,
attrib,
MVCPU_WIN_ENABLE));
} else {
- mvebu_mmc_write(WINDOW_CTRL(i), MVCPU_WIN_DISABLE);
+ mvebu_mmc_write(mmc, WINDOW_CTRL(i), MVCPU_WIN_DISABLE);
}
- mvebu_mmc_write(WINDOW_BASE(i), base);
+ mvebu_mmc_write(mmc, WINDOW_BASE(i), base);
}
}
-static int mvebu_mmc_initialize(struct mmc *mmc)
+static int mvebu_mmc_initialize(struct udevice *dev)
{
- debug("%s: mvebu_mmc_initialize\n", DRIVER_NAME);
+ struct mvebu_mmc_plat *pdata = dev_get_plat(dev);
+ struct mmc *mmc = &pdata->mmc;
+
+ dev_dbg(dev, "%s\n", __func__);
/*
* Setting host parameters
* Initial Host Ctrl : Timeout : max , Normal Speed mode,
* 4-bit data mode, Big Endian, SD memory Card, Push_pull CMD Line
*/
- mvebu_mmc_write(SDIO_HOST_CTRL,
+ mvebu_mmc_write(mmc, SDIO_HOST_CTRL,
SDIO_HOST_CTRL_TMOUT(SDIO_HOST_CTRL_TMOUT_MAX) |
SDIO_HOST_CTRL_DATA_WIDTH_4_BITS |
SDIO_HOST_CTRL_BIG_ENDIAN |
SDIO_HOST_CTRL_PUSH_PULL_EN |
SDIO_HOST_CTRL_CARD_TYPE_MEM_ONLY);
- mvebu_mmc_write(SDIO_CLK_CTRL, 0);
+ mvebu_mmc_write(mmc, SDIO_CLK_CTRL, 0);
/* enable status */
- mvebu_mmc_write(SDIO_NOR_STATUS_EN, SDIO_POLL_MASK);
- mvebu_mmc_write(SDIO_ERR_STATUS_EN, SDIO_POLL_MASK);
+ mvebu_mmc_write(mmc, SDIO_NOR_STATUS_EN, SDIO_POLL_MASK);
+ mvebu_mmc_write(mmc, SDIO_ERR_STATUS_EN, SDIO_POLL_MASK);
/* disable interrupts */
- mvebu_mmc_write(SDIO_NOR_INTR_EN, 0);
- mvebu_mmc_write(SDIO_ERR_INTR_EN, 0);
+ mvebu_mmc_write(mmc, SDIO_NOR_INTR_EN, 0);
+ mvebu_mmc_write(mmc, SDIO_ERR_INTR_EN, 0);
- mvebu_window_setup();
+ mvebu_window_setup(mmc);
/* SW reset */
- mvebu_mmc_write(SDIO_SW_RESET, SDIO_SW_RESET_NOW);
+ mvebu_mmc_write(mmc, SDIO_SW_RESET, SDIO_SW_RESET_NOW);
return 0;
}
-static const struct mmc_ops mvebu_mmc_ops = {
- .send_cmd = mvebu_mmc_send_cmd,
- .set_ios = mvebu_mmc_set_ios,
- .init = mvebu_mmc_initialize,
-};
+static int mvebu_mmc_of_to_plat(struct udevice *dev)
+{
+ struct mvebu_mmc_plat *pdata = dev_get_plat(dev);
+ fdt_addr_t addr;
-static struct mmc_config mvebu_mmc_cfg = {
- .name = DRIVER_NAME,
- .ops = &mvebu_mmc_ops,
- .f_min = MVEBU_MMC_BASE_FAST_CLOCK / MVEBU_MMC_BASE_DIV_MAX,
- .f_max = MVEBU_MMC_CLOCKRATE_MAX,
- .voltages = MMC_VDD_32_33 | MMC_VDD_33_34,
- .host_caps = MMC_MODE_4BIT | MMC_MODE_HS |
- MMC_MODE_HS_52MHz,
- .part_type = PART_TYPE_DOS,
- .b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT,
-};
+ addr = dev_read_addr(dev);
+ if (addr == FDT_ADDR_T_NONE)
+ return -EINVAL;
-int mvebu_mmc_init(struct bd_info *bis)
-{
- struct mmc *mmc;
+ pdata->iobase = (void *)addr;
- mvebu_mmc_power_up();
+ return 0;
+}
- mmc = mmc_create(&mvebu_mmc_cfg, bis);
- if (mmc == NULL)
- return -1;
+static int mvebu_mmc_probe(struct udevice *dev)
+{
+ struct mvebu_mmc_plat *pdata = dev_get_plat(dev);
+ struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+ struct mmc *mmc = &pdata->mmc;
+ struct mmc_config *cfg = &pdata->cfg;
+
+ cfg->name = dev->name;
+ cfg->f_min = MVEBU_MMC_BASE_FAST_CLOCK / MVEBU_MMC_BASE_DIV_MAX;
+ cfg->f_max = MVEBU_MMC_CLOCKRATE_MAX;
+ cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
+ cfg->host_caps = MMC_MODE_4BIT | MMC_MODE_HS | MMC_MODE_HS_52MHz;
+ cfg->part_type = PART_TYPE_DOS;
+ cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
+
+ mmc->cfg = cfg;
+ mmc->priv = pdata;
+ mmc->dev = dev;
+ upriv->mmc = mmc;
+
+ mvebu_mmc_power_up(dev);
+ mvebu_mmc_initialize(dev);
return 0;
}
+
+static const struct dm_mmc_ops mvebu_dm_mmc_ops = {
+ .send_cmd = mvebu_mmc_send_cmd,
+ .set_ios = mvebu_mmc_set_ios,
+};
+
+static int mvebu_mmc_bind(struct udevice *dev)
+{
+ struct mvebu_mmc_plat *pdata = dev_get_plat(dev);
+
+ return mmc_bind(dev, &pdata->mmc, &pdata->cfg);
+}
+
+static const struct udevice_id mvebu_mmc_match[] = {
+ { .compatible = "marvell,orion-sdio" },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(mvebu_mmc) = {
+ .name = "mvebu_mmc",
+ .id = UCLASS_MMC,
+ .of_match = mvebu_mmc_match,
+ .ops = &mvebu_dm_mmc_ops,
+ .probe = mvebu_mmc_probe,
+ .bind = mvebu_mmc_bind,
+ .of_to_plat = mvebu_mmc_of_to_plat,
+ .plat_auto = sizeof(struct mvebu_mmc_plat),
+};
diff --git a/drivers/mtd/nand/raw/mxs_nand_spl.c b/drivers/mtd/nand/raw/mxs_nand_spl.c
index 46dc29df369..17f46ae5e91 100644
--- a/drivers/mtd/nand/raw/mxs_nand_spl.c
+++ b/drivers/mtd/nand/raw/mxs_nand_spl.c
@@ -282,6 +282,11 @@ int nand_spl_load_image(uint32_t offs, unsigned int size, void *buf)
return 0;
}
+struct mtd_info *nand_get_mtd(void)
+{
+ return mtd;
+}
+
int nand_default_bbt(struct mtd_info *mtd)
{
return 0;
diff --git a/drivers/power/pmic/pmic_pca9450.c b/drivers/power/pmic/pmic_pca9450.c
index d4f27428bd1..8c4d0a92306 100644
--- a/drivers/power/pmic/pmic_pca9450.c
+++ b/drivers/power/pmic/pmic_pca9450.c
@@ -11,7 +11,7 @@
static const char pca9450_name[] = "PCA9450";
-int power_pca9450_init(unsigned char bus)
+int power_pca9450_init(unsigned char bus, unsigned char addr)
{
struct pmic *p = pmic_alloc();
@@ -23,7 +23,7 @@ int power_pca9450_init(unsigned char bus)
p->name = pca9450_name;
p->interface = PMIC_I2C;
p->number_of_regs = PCA9450_REG_NUM;
- p->hw.i2c.addr = 0x25;
+ p->hw.i2c.addr = addr;
p->hw.i2c.tx_num = 1;
p->bus = bus;
diff --git a/drivers/ram/sifive/Kconfig b/drivers/ram/sifive/Kconfig
index 6aca22ab2ab..08de692e026 100644
--- a/drivers/ram/sifive/Kconfig
+++ b/drivers/ram/sifive/Kconfig
@@ -8,6 +8,6 @@ config RAM_SIFIVE
config SIFIVE_FU540_DDR
bool "SiFive FU540 DDR driver"
depends on RAM_SIFIVE
- default y if TARGET_SIFIVE_FU540
+ default y if TARGET_SIFIVE_UNLEASHED
help
This enables DDR support for the platforms based on SiFive FU540 SoC.
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index f5b3f8826fb..019565f9796 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -166,7 +166,7 @@ config RESET_IPQ419
config RESET_SIFIVE
bool "Reset Driver for SiFive SoC's"
- depends on DM_RESET && CLK_SIFIVE_FU540_PRCI && TARGET_SIFIVE_FU540
+ depends on DM_RESET && CLK_SIFIVE_FU540_PRCI && TARGET_SIFIVE_UNLEASHED
default y
help
PRCI module within SiFive SoC's provides mechanism to reset
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index aa6d90158cd..dafba35279b 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -38,6 +38,13 @@ config RTC_ENABLE_32KHZ_OUTPUT
Some real-time clocks support the output of 32kHz square waves (such as ds3231),
the config symbol choose Real Time Clock device 32Khz output feature.
+config RTC_ARMADA38X
+ bool "Enable Armada 38x Marvell SoC RTC"
+ depends on DM_RTC && ARCH_MVEBU
+ help
+ This adds support for the in-chip RTC that can be found in the
+ Armada 38x Marvell's SoC devices.
+
config RTC_PCF2127
bool "Enable PCF2127 driver"
depends on DM_RTC
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 6a45a9c8749..15609e7b182 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_$(SPL_TPL_)DM_RTC) += rtc-uclass.o
obj-$(CONFIG_RTC_AT91SAM9_RTT) += at91sam9_rtt.o
obj-y += rtc-lib.o
+obj-$(CONFIG_RTC_ARMADA38X) += armada38x.o
obj-$(CONFIG_RTC_DAVINCI) += davinci.o
obj-$(CONFIG_RTC_DS1302) += ds1302.o
obj-$(CONFIG_RTC_DS1306) += ds1306.o
diff --git a/drivers/rtc/armada38x.c b/drivers/rtc/armada38x.c
new file mode 100644
index 00000000000..2d264acf779
--- /dev/null
+++ b/drivers/rtc/armada38x.c
@@ -0,0 +1,184 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * RTC driver for the Armada 38x Marvell SoCs
+ *
+ * Copyright (C) 2021 Marek Behun <marek.behun@nic.cz>
+ *
+ * Based on Linux' driver by Gregory Clement and Marvell
+ */
+
+#include <asm/io.h>
+#include <dm.h>
+#include <linux/delay.h>
+#include <rtc.h>
+
+#define RTC_STATUS 0x0
+#define RTC_TIME 0xC
+#define RTC_CONF_TEST 0x1C
+
+/* Armada38x SoC registers */
+#define RTC_38X_BRIDGE_TIMING_CTL 0x0
+#define RTC_38X_PERIOD_OFFS 0
+#define RTC_38X_PERIOD_MASK (0x3FF << RTC_38X_PERIOD_OFFS)
+#define RTC_38X_READ_DELAY_OFFS 26
+#define RTC_38X_READ_DELAY_MASK (0x1F << RTC_38X_READ_DELAY_OFFS)
+
+#define SAMPLE_NR 100
+
+struct armada38x_rtc {
+ void __iomem *regs;
+ void __iomem *regs_soc;
+};
+
+/*
+ * According to Erratum RES-3124064 we have to do some configuration in MBUS.
+ * To read an RTC register we need to read it 100 times and return the most
+ * frequent value.
+ * To write an RTC register we need to write 2x zero into STATUS register,
+ * followed by the proper write. Linux adds an 5 us delay after this, so we do
+ * it here as well.
+ */
+static void update_38x_mbus_timing_params(struct armada38x_rtc *rtc)
+{
+ u32 reg;
+
+ reg = readl(rtc->regs_soc + RTC_38X_BRIDGE_TIMING_CTL);
+ reg &= ~RTC_38X_PERIOD_MASK;
+ reg |= 0x3FF << RTC_38X_PERIOD_OFFS; /* Maximum value */
+ reg &= ~RTC_38X_READ_DELAY_MASK;
+ reg |= 0x1F << RTC_38X_READ_DELAY_OFFS; /* Maximum value */
+ writel(reg, rtc->regs_soc + RTC_38X_BRIDGE_TIMING_CTL);
+}
+
+static void armada38x_rtc_write(u32 val, struct armada38x_rtc *rtc, u8 reg)
+{
+ writel(0, rtc->regs + RTC_STATUS);
+ writel(0, rtc->regs + RTC_STATUS);
+ writel(val, rtc->regs + reg);
+ udelay(5);
+}
+
+static u32 armada38x_rtc_read(struct armada38x_rtc *rtc, u8 reg)
+{
+ u8 counts[SAMPLE_NR], max_idx;
+ u32 samples[SAMPLE_NR], max;
+ int i, j, last;
+
+ for (i = 0, last = 0; i < SAMPLE_NR; ++i) {
+ u32 sample = readl(rtc->regs + reg);
+
+ /* find if this value was already read */
+ for (j = 0; j < last; ++j) {
+ if (samples[j] == sample)
+ break;
+ }
+
+ if (j < last) {
+ /* if yes, increment count */
+ ++counts[j];
+ } else {
+ /* if not, add */
+ samples[last] = sample;
+ counts[last] = 1;
+ ++last;
+ }
+ }
+
+ /* finally find the sample that was read the most */
+ max = 0;
+ max_idx = 0;
+
+ for (i = 0; i < last; ++i) {
+ if (counts[i] > max) {
+ max = counts[i];
+ max_idx = i;
+ }
+ }
+
+ return samples[max_idx];
+}
+
+static int armada38x_rtc_get(struct udevice *dev, struct rtc_time *tm)
+{
+ struct armada38x_rtc *rtc = dev_get_priv(dev);
+ u32 time;
+
+ time = armada38x_rtc_read(rtc, RTC_TIME);
+
+ rtc_to_tm(time, tm);
+
+ return 0;
+}
+
+static int armada38x_rtc_reset(struct udevice *dev)
+{
+ struct armada38x_rtc *rtc = dev_get_priv(dev);
+ u32 reg;
+
+ reg = armada38x_rtc_read(rtc, RTC_CONF_TEST);
+
+ if (reg & 0xff) {
+ armada38x_rtc_write(0, rtc, RTC_CONF_TEST);
+ mdelay(500);
+ armada38x_rtc_write(0, rtc, RTC_TIME);
+ armada38x_rtc_write(BIT(0) | BIT(1), 0, RTC_STATUS);
+ }
+
+ return 0;
+}
+
+static int armada38x_rtc_set(struct udevice *dev, const struct rtc_time *tm)
+{
+ struct armada38x_rtc *rtc = dev_get_priv(dev);
+ unsigned long time;
+
+ time = rtc_mktime(tm);
+
+ if (time > U32_MAX)
+ printf("%s: requested time to set will overflow\n", dev->name);
+
+ armada38x_rtc_reset(dev);
+ armada38x_rtc_write(time, rtc, RTC_TIME);
+
+ return 0;
+}
+
+static int armada38x_probe(struct udevice *dev)
+{
+ struct armada38x_rtc *rtc = dev_get_priv(dev);
+
+ rtc->regs = dev_remap_addr_name(dev, "rtc");
+ if (!rtc->regs)
+ goto err;
+
+ rtc->regs_soc = dev_remap_addr_name(dev, "rtc-soc");
+ if (!rtc->regs_soc)
+ goto err;
+
+ update_38x_mbus_timing_params(rtc);
+
+ return 0;
+err:
+ printf("%s: io address missing\n", dev->name);
+ return -ENODEV;
+}
+
+static const struct rtc_ops armada38x_rtc_ops = {
+ .get = armada38x_rtc_get,
+ .set = armada38x_rtc_set,
+ .reset = armada38x_rtc_reset,
+};
+
+static const struct udevice_id armada38x_rtc_ids[] = {
+ { .compatible = "marvell,armada-380-rtc", .data = 0 },
+ { }
+};
+
+U_BOOT_DRIVER(rtc_armada38x) = {
+ .name = "rtc-armada38x",
+ .id = UCLASS_RTC,
+ .of_match = armada38x_rtc_ids,
+ .probe = armada38x_probe,
+ .priv_auto = sizeof(struct armada38x_rtc),
+ .ops = &armada38x_rtc_ops,
+};
diff --git a/drivers/timer/sifive_clint_timer.c b/drivers/timer/sifive_clint_timer.c
index de7b4b95c9e..939b99d937d 100644
--- a/drivers/timer/sifive_clint_timer.c
+++ b/drivers/timer/sifive_clint_timer.c
@@ -54,6 +54,7 @@ static int sifive_clint_probe(struct udevice *dev)
static const struct udevice_id sifive_clint_ids[] = {
{ .compatible = "riscv,clint0" },
+ { .compatible = "sifive,clint0" },
{ }
};
diff --git a/drivers/watchdog/designware_wdt.c b/drivers/watchdog/designware_wdt.c
index c020324973e..9e5487168cd 100644
--- a/drivers/watchdog/designware_wdt.c
+++ b/drivers/watchdog/designware_wdt.c
@@ -9,7 +9,6 @@
#include <reset.h>
#include <wdt.h>
#include <asm/io.h>
-#include <asm/utils.h>
#include <linux/bitops.h>
#define DW_WDT_CR 0x00
@@ -35,7 +34,7 @@ static int designware_wdt_settimeout(void __iomem *base, unsigned int clk_khz,
signed int i;
/* calculate the timeout range value */
- i = log_2_n_round_up(timeout * clk_khz) - 16;
+ i = fls(timeout * clk_khz - 1) - 16;
i = clamp(i, 0, 15);
writel(i | (i << 4), base + DW_WDT_TORR);
@@ -130,27 +129,39 @@ static int designware_wdt_probe(struct udevice *dev)
if (ret)
return ret;
+ ret = clk_enable(&clk);
+ if (ret)
+ goto err;
+
priv->clk_khz = clk_get_rate(&clk) / 1000;
- if (!priv->clk_khz)
- return -EINVAL;
+ if (!priv->clk_khz) {
+ ret = -EINVAL;
+ goto err;
+ }
#else
priv->clk_khz = CONFIG_DW_WDT_CLOCK_KHZ;
#endif
-#if CONFIG_IS_ENABLED(DM_RESET)
- struct reset_ctl_bulk resets;
+ if (CONFIG_IS_ENABLED(DM_RESET)) {
+ struct reset_ctl_bulk resets;
- ret = reset_get_bulk(dev, &resets);
- if (ret)
- return ret;
+ ret = reset_get_bulk(dev, &resets);
+ if (ret)
+ goto err;
- ret = reset_deassert_bulk(&resets);
- if (ret)
- return ret;
-#endif
+ ret = reset_deassert_bulk(&resets);
+ if (ret)
+ goto err;
+ }
/* reset to disable the watchdog */
return designware_wdt_stop(dev);
+
+err:
+#if CONFIG_IS_ENABLED(CLK)
+ clk_free(&clk);
+#endif
+ return ret;
}
static const struct wdt_ops designware_wdt_ops = {