diff options
Diffstat (limited to 'drivers')
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(®s->irba_h, ip_base >> 32); #else sec_out32(®s->irba_h, 0x0); #endif sec_out32(®s->irba_l, (uint32_t)ip_base); -#ifdef CONFIG_PHYS_64BIT +#ifdef CONFIG_CAAM_64BIT sec_out32(®s->orba_h, op_base >> 32); #else sec_out32(®s->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(®s->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(®s->vendorspec, VENDORSPEC_CKEN); + esdhc_clrbits32(®s->vendorspec, VENDORSPEC_FRC_SDCLK_ON); + ret = readx_poll_timeout(esdhc_read32, ®s->prsstat, tmp, tmp & PRSSTAT_SDOFF, 100); + if (ret) + pr_warn("fsl_esdhc_imx: Internal clock never gate off.\n"); #else esdhc_clrbits32(®s->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(®s->vendorspec, VENDORSPEC_PEREN | VENDORSPEC_CKEN); + esdhc_setbits32(®s->vendorspec, VENDORSPEC_FRC_SDCLK_ON); #else esdhc_setbits32(®s->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(®s->vendorspec, VENDORSPEC_FRC_SDCLK_ON); + ret = readx_poll_timeout(esdhc_read32, ®s->prsstat, tmp, tmp & PRSSTAT_SDOFF, 100); + if (ret) + pr_warn("fsl_esdhc_imx: Internal clock never gate off.\n"); esdhc_write32(®s->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(®s->vendorspec, VENDORSPEC_FRC_SDCLK_ON); } } @@ -835,6 +838,14 @@ static int esdhc_set_voltage(struct mmc *mmc) } #endif esdhc_setbits32(®s->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(®s->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(®s->vendorspec, VENDORSPEC_CKEN); + u32 tmp; + + esdhc_clrbits32(®s->vendorspec, VENDORSPEC_FRC_SDCLK_ON); + ret = readx_poll_timeout(esdhc_read32, ®s->prsstat, tmp, tmp & PRSSTAT_SDOFF, 100); + if (ret) + pr_warn("fsl_esdhc_imx: Internal clock never gate off.\n"); #else esdhc_clrbits32(®s->sysctl, SYSCTL_CKEN); #endif } else { #ifdef CONFIG_FSL_USDHC - esdhc_setbits32(®s->vendorspec, VENDORSPEC_PEREN | - VENDORSPEC_CKEN); + esdhc_setbits32(®s->vendorspec, VENDORSPEC_FRC_SDCLK_ON); #else esdhc_setbits32(®s->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(®s->sysctl, SYSCTL_HCKEN | SYSCTL_IPGEN); #else - esdhc_setbits32(®s->vendorspec, VENDORSPEC_HCKEN | VENDORSPEC_IPGEN); + esdhc_setbits32(®s->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(®s->autoc12err, 0); esdhc_write32(®s->clktunectrlstatus, 0); #else - esdhc_setbits32(®s->vendorspec, VENDORSPEC_PEREN | - VENDORSPEC_HCKEN | VENDORSPEC_IPGEN | VENDORSPEC_CKEN); + esdhc_setbits32(®s->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 = { |
