summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2016-05-24 13:42:03 -0400
committerTom Rini <trini@konsulko.com>2016-05-24 13:42:03 -0400
commitfc15b9beed05dec6cc092c265042381a0eadb0e9 (patch)
tree2b256906815661689177279d7cd23e30827c377b /drivers
parent2ee490a0245b65826a8ce8e42e34c9bf805d3656 (diff)
parentbc323b3fa7cbf1008f02d342c0505231961b5fa6 (diff)
downloadblackbird-obmc-uboot-fc15b9beed05dec6cc092c265042381a0eadb0e9.tar.gz
blackbird-obmc-uboot-fc15b9beed05dec6cc092c265042381a0eadb0e9.zip
Merge branch 'master' of git://git.denx.de/u-boot-fsl-qoriq
Diffstat (limited to 'drivers')
-rw-r--r--drivers/crypto/fsl/jr.c271
-rw-r--r--drivers/crypto/fsl/jr.h3
-rw-r--r--drivers/ddr/fsl/fsl_ddr_gen4.c27
-rw-r--r--drivers/mtd/spi/sf_internal.h5
-rw-r--r--drivers/mtd/spi/spi_flash.c72
-rw-r--r--drivers/spi/fsl_qspi.c159
6 files changed, 381 insertions, 156 deletions
diff --git a/drivers/crypto/fsl/jr.c b/drivers/crypto/fsl/jr.c
index 8bc517dadc..510fa4e376 100644
--- a/drivers/crypto/fsl/jr.c
+++ b/drivers/crypto/fsl/jr.c
@@ -19,11 +19,26 @@
#define CIRC_CNT(head, tail, size) (((head) - (tail)) & (size - 1))
#define CIRC_SPACE(head, tail, size) CIRC_CNT((tail), (head) + 1, (size))
-struct jobring jr;
+uint32_t sec_offset[CONFIG_SYS_FSL_MAX_NUM_OF_SEC] = {
+ 0,
+#if defined(CONFIG_PPC_C29X)
+ CONFIG_SYS_FSL_SEC_IDX_OFFSET,
+ 2 * CONFIG_SYS_FSL_SEC_IDX_OFFSET
+#endif
+};
+
+#define SEC_ADDR(idx) \
+ ((CONFIG_SYS_FSL_SEC_ADDR + sec_offset[idx]))
+
+#define SEC_JR0_ADDR(idx) \
+ (SEC_ADDR(idx) + \
+ (CONFIG_SYS_FSL_JR0_OFFSET - CONFIG_SYS_FSL_SEC_OFFSET))
+
+struct jobring jr0[CONFIG_SYS_FSL_MAX_NUM_OF_SEC];
-static inline void start_jr0(void)
+static inline void start_jr0(uint8_t sec_idx)
{
- ccsr_sec_t *sec = (void *)CONFIG_SYS_FSL_SEC_ADDR;
+ ccsr_sec_t *sec = (void *)SEC_ADDR(sec_idx);
u32 ctpr_ms = sec_in32(&sec->ctpr_ms);
u32 scfgr = sec_in32(&sec->scfgr);
@@ -42,15 +57,15 @@ static inline void start_jr0(void)
}
}
-static inline void jr_reset_liodn(void)
+static inline void jr_reset_liodn(uint8_t sec_idx)
{
- ccsr_sec_t *sec = (void *)CONFIG_SYS_FSL_SEC_ADDR;
+ ccsr_sec_t *sec = (void *)SEC_ADDR(sec_idx);
sec_out32(&sec->jrliodnr[0].ls, 0);
}
-static inline void jr_disable_irq(void)
+static inline void jr_disable_irq(uint8_t sec_idx)
{
- struct jr_regs *regs = (struct jr_regs *)CONFIG_SYS_FSL_JR0_ADDR;
+ struct jr_regs *regs = (struct jr_regs *)SEC_JR0_ADDR(sec_idx);
uint32_t jrcfg = sec_in32(&regs->jrcfg1);
jrcfg = jrcfg | JR_INTMASK;
@@ -58,11 +73,12 @@ static inline void jr_disable_irq(void)
sec_out32(&regs->jrcfg1, jrcfg);
}
-static void jr_initregs(void)
+static void jr_initregs(uint8_t sec_idx)
{
- struct jr_regs *regs = (struct jr_regs *)CONFIG_SYS_FSL_JR0_ADDR;
- phys_addr_t ip_base = virt_to_phys((void *)jr.input_ring);
- phys_addr_t op_base = virt_to_phys((void *)jr.output_ring);
+ 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);
#ifdef CONFIG_PHYS_64BIT
sec_out32(&regs->irba_h, ip_base >> 32);
@@ -79,59 +95,63 @@ static void jr_initregs(void)
sec_out32(&regs->ors, JR_SIZE);
sec_out32(&regs->irs, JR_SIZE);
- if (!jr.irq)
- jr_disable_irq();
+ if (!jr->irq)
+ jr_disable_irq(sec_idx);
}
-static int jr_init(void)
+static int jr_init(uint8_t sec_idx)
{
- memset(&jr, 0, sizeof(struct jobring));
+ struct jobring *jr = &jr0[sec_idx];
- jr.jq_id = DEFAULT_JR_ID;
- jr.irq = DEFAULT_IRQ;
+ memset(jr, 0, sizeof(struct jobring));
+
+ jr->jq_id = DEFAULT_JR_ID;
+ jr->irq = DEFAULT_IRQ;
#ifdef CONFIG_FSL_CORENET
- jr.liodn = DEFAULT_JR_LIODN;
+ jr->liodn = DEFAULT_JR_LIODN;
#endif
- jr.size = JR_SIZE;
- jr.input_ring = (dma_addr_t *)memalign(ARCH_DMA_MINALIGN,
+ jr->size = JR_SIZE;
+ jr->input_ring = (dma_addr_t *)memalign(ARCH_DMA_MINALIGN,
JR_SIZE * sizeof(dma_addr_t));
- if (!jr.input_ring)
+ if (!jr->input_ring)
return -1;
- jr.op_size = roundup(JR_SIZE * sizeof(struct op_ring),
- ARCH_DMA_MINALIGN);
- jr.output_ring =
- (struct op_ring *)memalign(ARCH_DMA_MINALIGN, jr.op_size);
- if (!jr.output_ring)
+ jr->op_size = roundup(JR_SIZE * sizeof(struct op_ring),
+ ARCH_DMA_MINALIGN);
+ jr->output_ring =
+ (struct op_ring *)memalign(ARCH_DMA_MINALIGN, jr->op_size);
+ if (!jr->output_ring)
return -1;
- memset(jr.input_ring, 0, JR_SIZE * sizeof(dma_addr_t));
- memset(jr.output_ring, 0, jr.op_size);
+ memset(jr->input_ring, 0, JR_SIZE * sizeof(dma_addr_t));
+ memset(jr->output_ring, 0, jr->op_size);
- start_jr0();
+ start_jr0(sec_idx);
- jr_initregs();
+ jr_initregs(sec_idx);
return 0;
}
-static int jr_sw_cleanup(void)
+static int jr_sw_cleanup(uint8_t sec_idx)
{
- jr.head = 0;
- jr.tail = 0;
- 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.output_ring, 0, jr.size * sizeof(struct op_ring));
+ struct jobring *jr = &jr0[sec_idx];
+
+ jr->head = 0;
+ jr->tail = 0;
+ 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->output_ring, 0, jr->size * sizeof(struct op_ring));
return 0;
}
-static int jr_hw_reset(void)
+static int jr_hw_reset(uint8_t sec_idx)
{
- struct jr_regs *regs = (struct jr_regs *)CONFIG_SYS_FSL_JR0_ADDR;
+ struct jr_regs *regs = (struct jr_regs *)SEC_JR0_ADDR(sec_idx);
uint32_t timeout = 100000;
uint32_t jrint, jrcr;
@@ -161,10 +181,11 @@ static int jr_hw_reset(void)
/* -1 --- error, can't enqueue -- no space available */
static int jr_enqueue(uint32_t *desc_addr,
void (*callback)(uint32_t status, void *arg),
- void *arg)
+ void *arg, uint8_t sec_idx)
{
- struct jr_regs *regs = (struct jr_regs *)CONFIG_SYS_FSL_JR0_ADDR;
- int head = jr.head;
+ struct jr_regs *regs = (struct jr_regs *)SEC_JR0_ADDR(sec_idx);
+ struct jobring *jr = &jr0[sec_idx];
+ int head = jr->head;
uint32_t desc_word;
int length = desc_len(desc_addr);
int i;
@@ -184,18 +205,14 @@ static int jr_enqueue(uint32_t *desc_addr,
phys_addr_t desc_phys_addr = virt_to_phys(desc_addr);
- if (sec_in32(&regs->irsa) == 0 ||
- CIRC_SPACE(jr.head, jr.tail, jr.size) <= 0)
- return -1;
-
- jr.info[head].desc_phys_addr = desc_phys_addr;
- jr.info[head].callback = (void *)callback;
- jr.info[head].arg = arg;
- jr.info[head].op_done = 0;
+ jr->info[head].desc_phys_addr = desc_phys_addr;
+ jr->info[head].callback = (void *)callback;
+ jr->info[head].arg = arg;
+ jr->info[head].op_done = 0;
- unsigned long start = (unsigned long)&jr.info[head] &
+ unsigned long start = (unsigned long)&jr->info[head] &
~(ARCH_DMA_MINALIGN - 1);
- unsigned long end = ALIGN((unsigned long)&jr.info[head] +
+ unsigned long end = ALIGN((unsigned long)&jr->info[head] +
sizeof(struct jr_info), ARCH_DMA_MINALIGN);
flush_dcache_range(start, end);
@@ -205,11 +222,11 @@ static int jr_enqueue(uint32_t *desc_addr,
* depend on endianness of SEC block.
*/
#ifdef CONFIG_SYS_FSL_SEC_LE
- addr_lo = (uint32_t *)(&jr.input_ring[head]);
- addr_hi = (uint32_t *)(&jr.input_ring[head]) + 1;
+ addr_lo = (uint32_t *)(&jr->input_ring[head]);
+ addr_hi = (uint32_t *)(&jr->input_ring[head]) + 1;
#elif defined(CONFIG_SYS_FSL_SEC_BE)
- addr_hi = (uint32_t *)(&jr.input_ring[head]);
- addr_lo = (uint32_t *)(&jr.input_ring[head]) + 1;
+ addr_hi = (uint32_t *)(&jr->input_ring[head]);
+ addr_lo = (uint32_t *)(&jr->input_ring[head]) + 1;
#endif /* ifdef CONFIG_SYS_FSL_SEC_LE */
sec_out32(addr_hi, (uint32_t)(desc_phys_addr >> 32));
@@ -217,21 +234,21 @@ 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);
+ sec_out32(&jr->input_ring[head], desc_phys_addr);
#endif /* ifdef CONFIG_PHYS_64BIT */
- start = (unsigned long)&jr.input_ring[head] & ~(ARCH_DMA_MINALIGN - 1);
- end = ALIGN((unsigned long)&jr.input_ring[head] +
+ 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);
flush_dcache_range(start, end);
- jr.head = (head + 1) & (jr.size - 1);
+ jr->head = (head + 1) & (jr->size - 1);
/* Invalidate output ring */
- start = (unsigned long)jr.output_ring &
+ start = (unsigned long)jr->output_ring &
~(ARCH_DMA_MINALIGN - 1);
- end = ALIGN((unsigned long)jr.output_ring + jr.op_size,
- ARCH_DMA_MINALIGN);
+ end = ALIGN((unsigned long)jr->output_ring + jr->op_size,
+ ARCH_DMA_MINALIGN);
invalidate_dcache_range(start, end);
sec_out32(&regs->irja, 1);
@@ -239,11 +256,12 @@ static int jr_enqueue(uint32_t *desc_addr,
return 0;
}
-static int jr_dequeue(void)
+static int jr_dequeue(int sec_idx)
{
- struct jr_regs *regs = (struct jr_regs *)CONFIG_SYS_FSL_JR0_ADDR;
- int head = jr.head;
- int tail = jr.tail;
+ struct jr_regs *regs = (struct jr_regs *)SEC_JR0_ADDR(sec_idx);
+ struct jobring *jr = &jr0[sec_idx];
+ int head = jr->head;
+ int tail = jr->tail;
int idx, i, found;
void (*callback)(uint32_t status, void *arg);
void *arg = NULL;
@@ -253,7 +271,8 @@ static int jr_dequeue(void)
uint32_t *addr;
#endif
- while (sec_in32(&regs->orsf) && CIRC_CNT(jr.head, jr.tail, jr.size)) {
+ while (sec_in32(&regs->orsf) && CIRC_CNT(jr->head, jr->tail,
+ jr->size)) {
found = 0;
@@ -264,11 +283,11 @@ static int jr_dequeue(void)
* depend on endianness of SEC block.
*/
#ifdef CONFIG_SYS_FSL_SEC_LE
- addr_lo = (uint32_t *)(&jr.output_ring[jr.tail].desc);
- addr_hi = (uint32_t *)(&jr.output_ring[jr.tail].desc) + 1;
+ addr_lo = (uint32_t *)(&jr->output_ring[jr->tail].desc);
+ addr_hi = (uint32_t *)(&jr->output_ring[jr->tail].desc) + 1;
#elif defined(CONFIG_SYS_FSL_SEC_BE)
- addr_hi = (uint32_t *)(&jr.output_ring[jr.tail].desc);
- addr_lo = (uint32_t *)(&jr.output_ring[jr.tail].desc) + 1;
+ addr_hi = (uint32_t *)(&jr->output_ring[jr->tail].desc);
+ addr_lo = (uint32_t *)(&jr->output_ring[jr->tail].desc) + 1;
#endif /* ifdef CONFIG_SYS_FSL_SEC_LE */
op_desc = ((u64)sec_in32(addr_hi) << 32) |
@@ -276,15 +295,15 @@ static int jr_dequeue(void)
#else
/* Read the 32 bit Descriptor address from Output Ring. */
- addr = (uint32_t *)&jr.output_ring[jr.tail].desc;
+ addr = (uint32_t *)&jr->output_ring[jr->tail].desc;
op_desc = sec_in32(addr);
#endif /* ifdef CONFIG_PHYS_64BIT */
- uint32_t status = sec_in32(&jr.output_ring[jr.tail].status);
+ uint32_t status = sec_in32(&jr->output_ring[jr->tail].status);
- for (i = 0; CIRC_CNT(head, tail + i, jr.size) >= 1; i++) {
- idx = (tail + i) & (jr.size - 1);
- if (op_desc == jr.info[idx].desc_phys_addr) {
+ for (i = 0; CIRC_CNT(head, tail + i, jr->size) >= 1; i++) {
+ idx = (tail + i) & (jr->size - 1);
+ if (op_desc == jr->info[idx].desc_phys_addr) {
found = 1;
break;
}
@@ -294,9 +313,9 @@ static int jr_dequeue(void)
if (!found)
return -1;
- jr.info[idx].op_done = 1;
- callback = (void *)jr.info[idx].callback;
- arg = jr.info[idx].arg;
+ jr->info[idx].op_done = 1;
+ callback = (void *)jr->info[idx].callback;
+ arg = jr->info[idx].arg;
/* When the job on tail idx gets done, increment
* tail till the point where job completed out of oredr has
@@ -304,14 +323,14 @@ static int jr_dequeue(void)
*/
if (idx == tail)
do {
- tail = (tail + 1) & (jr.size - 1);
- } while (jr.info[tail].op_done);
+ tail = (tail + 1) & (jr->size - 1);
+ } while (jr->info[tail].op_done);
- jr.tail = tail;
- jr.read_idx = (jr.read_idx + 1) & (jr.size - 1);
+ jr->tail = tail;
+ jr->read_idx = (jr->read_idx + 1) & (jr->size - 1);
sec_out32(&regs->orjr, 1);
- jr.info[idx].op_done = 0;
+ jr->info[idx].op_done = 0;
callback(status, arg);
}
@@ -327,7 +346,7 @@ static void desc_done(uint32_t status, void *arg)
x->done = 1;
}
-int run_descriptor_jr(uint32_t *desc)
+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);
@@ -336,7 +355,7 @@ int run_descriptor_jr(uint32_t *desc)
memset(&op, 0, sizeof(op));
- ret = jr_enqueue(desc, desc_done, &op);
+ ret = jr_enqueue(desc, desc_done, &op, sec_idx);
if (ret) {
debug("Error in SEC enq\n");
ret = JQ_ENQ_ERR;
@@ -346,7 +365,7 @@ int run_descriptor_jr(uint32_t *desc)
timeval = get_ticks();
timeout = usec2ticks(CONFIG_SEC_DEQ_TIMEOUT);
while (op.done != 1) {
- ret = jr_dequeue();
+ ret = jr_dequeue(sec_idx);
if (ret) {
debug("Error in SEC deq\n");
ret = JQ_DEQ_ERR;
@@ -368,20 +387,30 @@ out:
return ret;
}
-int jr_reset(void)
+int run_descriptor_jr(uint32_t *desc)
+{
+ return run_descriptor_jr_idx(desc, 0);
+}
+
+static inline int jr_reset_sec(uint8_t sec_idx)
{
- if (jr_hw_reset() < 0)
+ if (jr_hw_reset(sec_idx) < 0)
return -1;
/* Clean up the jobring structure maintained by software */
- jr_sw_cleanup();
+ jr_sw_cleanup(sec_idx);
return 0;
}
-int sec_reset(void)
+int jr_reset(void)
{
- ccsr_sec_t *sec = (void *)CONFIG_SYS_FSL_SEC_ADDR;
+ return jr_reset_sec(0);
+}
+
+static inline int sec_reset_idx(uint8_t sec_idx)
+{
+ ccsr_sec_t *sec = (void *)SEC_ADDR(sec_idx);
uint32_t mcfgr = sec_in32(&sec->mcfgr);
uint32_t timeout = 100000;
@@ -408,14 +437,13 @@ int sec_reset(void)
return 0;
}
-static int instantiate_rng(void)
+static int instantiate_rng(uint8_t sec_idx)
{
struct result op;
u32 *desc;
u32 rdsta_val;
int ret = 0;
- ccsr_sec_t __iomem *sec =
- (ccsr_sec_t __iomem *)CONFIG_SYS_FSL_SEC_ADDR;
+ ccsr_sec_t __iomem *sec = (ccsr_sec_t __iomem *)SEC_ADDR(sec_idx);
struct rng4tst __iomem *rng =
(struct rng4tst __iomem *)&sec->rng;
@@ -432,7 +460,7 @@ static int instantiate_rng(void)
flush_dcache_range((unsigned long)desc,
(unsigned long)desc + size);
- ret = run_descriptor_jr(desc);
+ ret = run_descriptor_jr_idx(desc, sec_idx);
if (ret)
printf("RNG: Instantiation failed with error %x\n", ret);
@@ -444,9 +472,14 @@ static int instantiate_rng(void)
return ret;
}
-static u8 get_rng_vid(void)
+int sec_reset(void)
+{
+ return sec_reset_idx(0);
+}
+
+static u8 get_rng_vid(uint8_t sec_idx)
{
- ccsr_sec_t *sec = (void *)CONFIG_SYS_FSL_SEC_ADDR;
+ ccsr_sec_t *sec = (void *)SEC_ADDR(sec_idx);
u32 cha_vid = sec_in32(&sec->chavid_ls);
return (cha_vid & SEC_CHAVID_RNG_LS_MASK) >> SEC_CHAVID_LS_RNG_SHIFT;
@@ -456,10 +489,9 @@ static u8 get_rng_vid(void)
* By default, the TRNG runs for 200 clocks per sample;
* 1200 clocks per sample generates better entropy.
*/
-static void kick_trng(int ent_delay)
+static void kick_trng(int ent_delay, uint8_t sec_idx)
{
- ccsr_sec_t __iomem *sec =
- (ccsr_sec_t __iomem *)CONFIG_SYS_FSL_SEC_ADDR;
+ ccsr_sec_t __iomem *sec = (ccsr_sec_t __iomem *)SEC_ADDR(sec_idx);
struct rng4tst __iomem *rng =
(struct rng4tst __iomem *)&sec->rng;
u32 val;
@@ -486,11 +518,10 @@ static void kick_trng(int ent_delay)
sec_clrbits32(&rng->rtmctl, RTMCTL_PRGM);
}
-static int rng_init(void)
+static int rng_init(uint8_t sec_idx)
{
int ret, ent_delay = RTSDCTL_ENT_DLY_MIN;
- ccsr_sec_t __iomem *sec =
- (ccsr_sec_t __iomem *)CONFIG_SYS_FSL_SEC_ADDR;
+ ccsr_sec_t __iomem *sec = (ccsr_sec_t __iomem *)SEC_ADDR(sec_idx);
struct rng4tst __iomem *rng =
(struct rng4tst __iomem *)&sec->rng;
@@ -509,7 +540,7 @@ static int rng_init(void)
* Also, if a handle was instantiated, do not change
* the TRNG parameters.
*/
- kick_trng(ent_delay);
+ kick_trng(ent_delay, sec_idx);
ent_delay += 400;
/*
* if instantiate_rng(...) fails, the loop will rerun
@@ -518,7 +549,7 @@ static int rng_init(void)
* interval, leading to a sucessful initialization of
* the RNG.
*/
- ret = instantiate_rng();
+ ret = instantiate_rng(sec_idx);
} while ((ret == -1) && (ent_delay < RTSDCTL_ENT_DLY_MAX));
if (ret) {
printf("RNG: Failed to instantiate RNG\n");
@@ -531,9 +562,9 @@ static int rng_init(void)
return ret;
}
-int sec_init(void)
+int sec_init_idx(uint8_t sec_idx)
{
- ccsr_sec_t *sec = (void *)CONFIG_SYS_FSL_SEC_ADDR;
+ ccsr_sec_t *sec = (void *)SEC_ADDR(sec_idx);
uint32_t mcr = sec_in32(&sec->mcfgr);
int ret = 0;
@@ -543,6 +574,11 @@ int sec_init(void)
uint32_t liodn_s;
#endif
+ if (!(sec_idx < CONFIG_SYS_FSL_MAX_NUM_OF_SEC)) {
+ printf("SEC initialization failed\n");
+ return -1;
+ }
+
/*
* Modifying CAAM Read/Write Attributes
* For LS2080A
@@ -568,7 +604,7 @@ int sec_init(void)
liodn_s = (liodnr & JRSLIODN_MASK) >> JRSLIODN_SHIFT;
#endif
- ret = jr_init();
+ ret = jr_init(sec_idx);
if (ret < 0) {
printf("SEC initialization failed\n");
return -1;
@@ -582,13 +618,18 @@ int sec_init(void)
pamu_enable();
#endif
- if (get_rng_vid() >= 4) {
- if (rng_init() < 0) {
- printf("RNG instantiation failed\n");
+ if (get_rng_vid(sec_idx) >= 4) {
+ if (rng_init(sec_idx) < 0) {
+ printf("SEC%u: RNG instantiation failed\n", sec_idx);
return -1;
}
- printf("SEC: RNG instantiated\n");
+ printf("SEC%u: RNG instantiated\n", sec_idx);
}
return ret;
}
+
+int sec_init(void)
+{
+ return sec_init_idx(0);
+}
diff --git a/drivers/crypto/fsl/jr.h b/drivers/crypto/fsl/jr.h
index 1642dbbf4c..d897e572d6 100644
--- a/drivers/crypto/fsl/jr.h
+++ b/drivers/crypto/fsl/jr.h
@@ -90,6 +90,9 @@ struct jobring {
/* This ring can be on the stack */
struct jr_info info[JR_SIZE];
struct op_ring *output_ring;
+ /* Offset in CCSR to the SEC engine to which this JR belongs */
+ uint32_t sec_offset;
+
};
struct result {
diff --git a/drivers/ddr/fsl/fsl_ddr_gen4.c b/drivers/ddr/fsl/fsl_ddr_gen4.c
index 608810d4e2..5039f5de0a 100644
--- a/drivers/ddr/fsl/fsl_ddr_gen4.c
+++ b/drivers/ddr/fsl/fsl_ddr_gen4.c
@@ -56,7 +56,8 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
u32 vref_seq2[3] = {0xc0, 0xf0, 0x70}; /* for range 2 */
u32 *vref_seq = vref_seq1;
#endif
-#ifdef CONFIG_SYS_FSL_ERRATUM_A009942
+#if defined(CONFIG_SYS_FSL_ERRATUM_A009942) | \
+ defined(CONFIG_SYS_FSL_ERRATUM_A010165)
ulong ddr_freq;
u32 tmp;
#endif
@@ -240,8 +241,10 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
/* Disable DRAM VRef training */
ddr_out32(&ddr->ddr_cdr2,
regs->ddr_cdr2 & ~DDR_CDR2_VREF_TRAIN_EN);
- /* Disable deskew */
- ddr_out32(&ddr->debug[28], 0x400);
+ /* disable transmit bit deskew */
+ temp32 = ddr_in32(&ddr->debug[28]);
+ temp32 |= DDR_TX_BD_DIS;
+ ddr_out32(&ddr->debug[28], temp32);
/* Disable D_INIT */
ddr_out32(&ddr->sdram_cfg_2,
regs->ddr_sdram_cfg_2 & ~SDRAM_CFG2_D_INIT);
@@ -249,6 +252,13 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
}
#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_A009801
+ temp32 = ddr_in32(&ddr->debug[25]);
+ temp32 &= ~DDR_CAS_TO_PRE_SUB_MASK;
+ temp32 |= 9 << DDR_CAS_TO_PRE_SUB_SHIFT;
+ ddr_out32(&ddr->debug[25], temp32);
+#endif
+
#ifdef CONFIG_SYS_FSL_ERRATUM_A009942
ddr_freq = get_ddr_freq(ctrl_num) / 1000000;
tmp = ddr_in32(&ddr->debug[28]);
@@ -262,6 +272,13 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
ddr_out32(&ddr->debug[28], tmp | 0x0060007b);
#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_A010165
+ ddr_freq = get_ddr_freq(ctrl_num) / 1000000;
+ if ((ddr_freq > 1900) && (ddr_freq < 2300)) {
+ tmp = ddr_in32(&ddr->debug[28]);
+ ddr_out32(&ddr->debug[28], tmp | 0x000a0000);
+ }
+#endif
/*
* For RDIMMs, JEDEC spec requires clocks to be stable before reset is
* deasserted. Clocks start when any chip select is enabled and clock
@@ -358,7 +375,9 @@ step2:
debug("MR6 = 0x%08x\n", temp32);
}
ddr_out32(&ddr->sdram_md_cntl, 0);
- ddr_out32(&ddr->debug[28], 0); /* Enable deskew */
+ temp32 = ddr_in32(&ddr->debug[28]);
+ temp32 &= ~DDR_TX_BD_DIS; /* Enable deskew */
+ ddr_out32(&ddr->debug[28], temp32);
ddr_out32(&ddr->debug[1], 0x400); /* restart deskew */
/* wait for idle */
timeout = 40;
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h
index 007a5a085c..da2bb7b5d2 100644
--- a/drivers/mtd/spi/sf_internal.h
+++ b/drivers/mtd/spi/sf_internal.h
@@ -127,6 +127,11 @@ int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len,
const void *buf);
#endif
+#ifdef CONFIG_SPI_FLASH_SPANSION
+/* Used for Spansion S25FS-S family flash only. */
+#define CMD_SPANSION_RDAR 0x65 /* Read any device register */
+#define CMD_SPANSION_WRAR 0x71 /* Write any device register */
+#endif
/**
* struct spi_flash_params - SPI/QSPI flash device params structure
*
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index 5451725689..fa0e79966c 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -971,6 +971,43 @@ int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash)
}
#endif /* CONFIG_IS_ENABLED(OF_CONTROL) */
+#ifdef CONFIG_SPI_FLASH_SPANSION
+static int spansion_s25fss_disable_4KB_erase(struct spi_slave *spi)
+{
+ u8 cmd[4];
+ u32 offset = 0x800004; /* CR3V register offset */
+ u8 cr3v;
+ int ret;
+
+ cmd[0] = CMD_SPANSION_RDAR;
+ cmd[1] = offset >> 16;
+ cmd[2] = offset >> 8;
+ cmd[3] = offset >> 0;
+
+ ret = spi_flash_cmd_read(spi, cmd, 4, &cr3v, 1);
+ if (ret)
+ return -EIO;
+ /* CR3V bit3: 4-KB Erase */
+ if (cr3v & 0x8)
+ return 0;
+
+ cmd[0] = CMD_SPANSION_WRAR;
+ cr3v |= 0x8;
+ ret = spi_flash_cmd_write(spi, cmd, 4, &cr3v, 1);
+ if (ret)
+ return -EIO;
+
+ cmd[0] = CMD_SPANSION_RDAR;
+ ret = spi_flash_cmd_read(spi, cmd, 4, &cr3v, 1);
+ if (ret)
+ return -EIO;
+ if (!(cr3v & 0x8))
+ return -EFAULT;
+
+ return 0;
+}
+#endif
+
int spi_flash_scan(struct spi_flash *flash)
{
struct spi_slave *spi = flash->spi;
@@ -1021,6 +1058,41 @@ int spi_flash_scan(struct spi_flash *flash)
return -EPROTONOSUPPORT;
}
+#ifdef CONFIG_SPI_FLASH_SPANSION
+ /*
+ * The S25FS-S family physical sectors may be configured as a
+ * hybrid combination of eight 4-kB parameter sectors
+ * at the top or bottom of the address space with all
+ * but one of the remaining sectors being uniform size.
+ * The Parameter Sector Erase commands (20h or 21h) must
+ * be used to erase the 4-kB parameter sectors individually.
+ * The Sector (uniform sector) Erase commands (D8h or DCh)
+ * must be used to erase any of the remaining
+ * sectors, including the portion of highest or lowest address
+ * sector that is not overlaid by the parameter sectors.
+ * The uniform sector erase command has no effect on parameter sectors.
+ */
+ if (jedec == 0x0219 && (ext_jedec & 0xff00) == 0x4d00) {
+ int ret;
+ u8 id[6];
+
+ /* Read the ID codes again, 6 bytes */
+ ret = spi_flash_cmd(flash->spi, CMD_READ_ID, id, sizeof(id));
+ if (ret)
+ return -EIO;
+
+ ret = memcmp(id, idcode, 5);
+ if (ret)
+ return -EIO;
+
+ /* 0x81: S25FS-S family 0x80: S25FL-S family */
+ if (id[5] == 0x81) {
+ ret = spansion_s25fss_disable_4KB_erase(spi);
+ if (ret)
+ return ret;
+ }
+ }
+#endif
/* Flash powers up read-only, so clear BP# bits */
if (idcode[0] == SPI_FLASH_CFI_MFR_ATMEL ||
idcode[0] == SPI_FLASH_CFI_MFR_MACRONIX ||
diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c
index cb8d929d07..75cbab2676 100644
--- a/drivers/spi/fsl_qspi.c
+++ b/drivers/spi/fsl_qspi.c
@@ -44,6 +44,8 @@ DECLARE_GLOBAL_DATA_PTR;
#define SEQID_RDEAR 11
#define SEQID_WREAR 12
#endif
+#define SEQID_WRAR 13
+#define SEQID_RDAR 14
/* QSPI CMD */
#define QSPI_CMD_PP 0x02 /* Page program (up to 256 bytes) */
@@ -63,6 +65,10 @@ DECLARE_GLOBAL_DATA_PTR;
#define QSPI_CMD_BRRD 0x16 /* Bank register read */
#define QSPI_CMD_BRWR 0x17 /* Bank register write */
+/* Used for Spansion S25FS-S family flash only. */
+#define QSPI_CMD_RDAR 0x65 /* Read any device register */
+#define QSPI_CMD_WRAR 0x71 /* Write any device register */
+
/* 4-byte address QSPI CMD - used on Spansion and some Macronix flashes */
#define QSPI_CMD_FAST_READ_4B 0x0c /* Read data bytes (high frequency) */
#define QSPI_CMD_PP_4B 0x12 /* Page program (up to 256 bytes) */
@@ -92,9 +98,9 @@ DECLARE_GLOBAL_DATA_PTR;
struct fsl_qspi_platdata {
u32 flags;
u32 speed_hz;
- u32 reg_base;
- u32 amba_base;
- u32 amba_total_size;
+ fdt_addr_t reg_base;
+ fdt_addr_t amba_base;
+ fdt_size_t amba_total_size;
u32 flash_num;
u32 num_chipselect;
};
@@ -317,6 +323,33 @@ static void qspi_set_lut(struct fsl_qspi_priv *priv)
PAD0(LUT_PAD1) | INSTR0(LUT_CMD) | OPRND1(1) |
PAD1(LUT_PAD1) | INSTR1(LUT_WRITE));
#endif
+
+ /*
+ * Read any device register.
+ * Used for Spansion S25FS-S family flash only.
+ */
+ lut_base = SEQID_RDAR * 4;
+ qspi_write32(priv->flags, &regs->lut[lut_base],
+ OPRND0(QSPI_CMD_RDAR) | PAD0(LUT_PAD1) |
+ INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) |
+ PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
+ qspi_write32(priv->flags, &regs->lut[lut_base + 1],
+ OPRND0(8) | PAD0(LUT_PAD1) | INSTR0(LUT_DUMMY) |
+ OPRND1(1) | PAD1(LUT_PAD1) |
+ INSTR1(LUT_READ));
+
+ /*
+ * Write any device register.
+ * Used for Spansion S25FS-S family flash only.
+ */
+ lut_base = SEQID_WRAR * 4;
+ qspi_write32(priv->flags, &regs->lut[lut_base],
+ OPRND0(QSPI_CMD_WRAR) | PAD0(LUT_PAD1) |
+ INSTR0(LUT_CMD) | OPRND1(ADDR24BIT) |
+ PAD1(LUT_PAD1) | INSTR1(LUT_ADDR));
+ qspi_write32(priv->flags, &regs->lut[lut_base + 1],
+ OPRND0(1) | PAD0(LUT_PAD1) | INSTR0(LUT_WRITE));
+
/* Lock the LUT */
qspi_write32(priv->flags, &regs->lutkey, LUT_KEY_VALUE);
qspi_write32(priv->flags, &regs->lckcr, QSPI_LCKCR_LOCK);
@@ -510,7 +543,6 @@ static void qspi_op_rdid(struct fsl_qspi_priv *priv, u32 *rxbuf, u32 len)
qspi_write32(priv->flags, &regs->mcr, mcr_reg);
}
-#ifndef CONFIG_SYS_FSL_QSPI_AHB
/* If not use AHB read, read data from ip interface */
static void qspi_op_read(struct fsl_qspi_priv *priv, u32 *rxbuf, u32 len)
{
@@ -518,6 +550,12 @@ static void qspi_op_read(struct fsl_qspi_priv *priv, u32 *rxbuf, u32 len)
u32 mcr_reg, data;
int i, size;
u32 to_or_from;
+ u32 seqid;
+
+ if (priv->cur_seqid == QSPI_CMD_RDAR)
+ seqid = SEQID_RDAR;
+ else
+ seqid = SEQID_FAST_READ;
mcr_reg = qspi_read32(priv->flags, &regs->mcr);
qspi_write32(priv->flags, &regs->mcr,
@@ -536,7 +574,7 @@ static void qspi_op_read(struct fsl_qspi_priv *priv, u32 *rxbuf, u32 len)
RX_BUFFER_SIZE : len;
qspi_write32(priv->flags, &regs->ipcr,
- (SEQID_FAST_READ << QSPI_IPCR_SEQID_SHIFT) |
+ (seqid << QSPI_IPCR_SEQID_SHIFT) |
size);
while (qspi_read32(priv->flags, &regs->sr) & QSPI_SR_BUSY_MASK)
;
@@ -548,7 +586,10 @@ static void qspi_op_read(struct fsl_qspi_priv *priv, u32 *rxbuf, u32 len)
while ((RX_BUFFER_SIZE >= size) && (size > 0)) {
data = qspi_read32(priv->flags, &regs->rbdr[i]);
data = qspi_endian_xchg(data);
- memcpy(rxbuf, &data, 4);
+ if (size < 4)
+ memcpy(rxbuf, &data, size);
+ else
+ memcpy(rxbuf, &data, 4);
rxbuf++;
size -= 4;
i++;
@@ -560,7 +601,6 @@ static void qspi_op_read(struct fsl_qspi_priv *priv, u32 *rxbuf, u32 len)
qspi_write32(priv->flags, &regs->mcr, mcr_reg);
}
-#endif
static void qspi_op_write(struct fsl_qspi_priv *priv, u8 *txbuf, u32 len)
{
@@ -601,6 +641,8 @@ static void qspi_op_write(struct fsl_qspi_priv *priv, u8 *txbuf, u32 len)
/* Default is page programming */
seqid = SEQID_PP;
+ if (priv->cur_seqid == QSPI_CMD_WRAR)
+ seqid = SEQID_WRAR;
#ifdef CONFIG_SPI_FLASH_BAR
if (priv->cur_seqid == QSPI_CMD_BRWR)
seqid = SEQID_BRWR;
@@ -725,13 +767,15 @@ int qspi_xfer(struct fsl_qspi_priv *priv, unsigned int bitlen,
return 0;
}
- if (priv->cur_seqid == QSPI_CMD_FAST_READ) {
+ if (priv->cur_seqid == QSPI_CMD_FAST_READ ||
+ priv->cur_seqid == QSPI_CMD_RDAR) {
priv->sf_addr = swab32(txbuf) & OFFSET_BITS_MASK;
} else if ((priv->cur_seqid == QSPI_CMD_SE) ||
(priv->cur_seqid == QSPI_CMD_BE_4K)) {
priv->sf_addr = swab32(txbuf) & OFFSET_BITS_MASK;
qspi_op_erase(priv);
- } else if (priv->cur_seqid == QSPI_CMD_PP) {
+ } else if (priv->cur_seqid == QSPI_CMD_PP ||
+ priv->cur_seqid == QSPI_CMD_WRAR) {
wr_sfaddr = swab32(txbuf) & OFFSET_BITS_MASK;
} else if ((priv->cur_seqid == QSPI_CMD_BRWR) ||
(priv->cur_seqid == QSPI_CMD_WREAR)) {
@@ -748,6 +792,8 @@ int qspi_xfer(struct fsl_qspi_priv *priv, unsigned int bitlen,
#else
qspi_op_read(priv, din, bytes);
#endif
+ } else if (priv->cur_seqid == QSPI_CMD_RDAR) {
+ qspi_op_read(priv, din, bytes);
} else if (priv->cur_seqid == QSPI_CMD_RDID)
qspi_op_rdid(priv, din, bytes);
else if (priv->cur_seqid == QSPI_CMD_RDSR)
@@ -927,10 +973,11 @@ static int fsl_qspi_child_pre_probe(struct udevice *dev)
static int fsl_qspi_probe(struct udevice *bus)
{
- u32 total_size;
+ u32 amba_size_per_chip;
struct fsl_qspi_platdata *plat = dev_get_platdata(bus);
struct fsl_qspi_priv *priv = dev_get_priv(bus);
struct dm_spi_bus *dm_spi_bus;
+ int i;
dm_spi_bus = bus->uclass_priv;
@@ -940,8 +987,13 @@ static int fsl_qspi_probe(struct udevice *bus)
priv->flags = plat->flags;
priv->speed_hz = plat->speed_hz;
- priv->amba_base[0] = plat->amba_base;
- priv->amba_total_size = plat->amba_total_size;
+ /*
+ * QSPI SFADR width is 32bits, the max dest addr is 4GB-1.
+ * AMBA memory zone should be located on the 0~4GB space
+ * even on a 64bits cpu.
+ */
+ priv->amba_base[0] = (u32)plat->amba_base;
+ priv->amba_total_size = (u32)plat->amba_total_size;
priv->flash_num = plat->flash_num;
priv->num_chipselect = plat->num_chipselect;
@@ -951,7 +1003,22 @@ static int fsl_qspi_probe(struct udevice *bus)
qspi_cfg_smpr(priv, ~(QSPI_SMPR_FSDLY_MASK | QSPI_SMPR_DDRSMP_MASK |
QSPI_SMPR_FSPHS_MASK | QSPI_SMPR_HSENA_MASK), 0);
- total_size = FSL_QSPI_FLASH_SIZE * FSL_QSPI_FLASH_NUM;
+ /*
+ * Assign AMBA memory zone for every chipselect
+ * QuadSPI has two channels, every channel has two chipselects.
+ * If the property 'num-cs' in dts is 2, the AMBA memory will be divided
+ * into two parts and assign to every channel. This indicate that every
+ * channel only has one valid chipselect.
+ * If the property 'num-cs' in dts is 4, the AMBA memory will be divided
+ * into four parts and assign to every chipselect.
+ * Every channel will has two valid chipselects.
+ */
+ amba_size_per_chip = priv->amba_total_size >>
+ (priv->num_chipselect >> 1);
+ for (i = 1 ; i < priv->num_chipselect ; i++)
+ priv->amba_base[i] =
+ amba_size_per_chip + priv->amba_base[i - 1];
+
/*
* Any read access to non-implemented addresses will provide
* undefined results.
@@ -962,14 +1029,30 @@ static int fsl_qspi_probe(struct udevice *bus)
* setting the size of these devices to 0. This would ensure
* that the complete memory map is assigned to only one flash device.
*/
- qspi_write32(priv->flags, &priv->regs->sfa1ad,
- FSL_QSPI_FLASH_SIZE | priv->amba_base[0]);
- qspi_write32(priv->flags, &priv->regs->sfa2ad,
- FSL_QSPI_FLASH_SIZE | priv->amba_base[0]);
- qspi_write32(priv->flags, &priv->regs->sfb1ad,
- total_size | priv->amba_base[0]);
- qspi_write32(priv->flags, &priv->regs->sfb2ad,
- total_size | priv->amba_base[0]);
+ qspi_write32(priv->flags, &priv->regs->sfa1ad, priv->amba_base[1]);
+ switch (priv->num_chipselect) {
+ case 2:
+ qspi_write32(priv->flags, &priv->regs->sfa2ad,
+ priv->amba_base[1]);
+ qspi_write32(priv->flags, &priv->regs->sfb1ad,
+ priv->amba_base[1] + amba_size_per_chip);
+ qspi_write32(priv->flags, &priv->regs->sfb2ad,
+ priv->amba_base[1] + amba_size_per_chip);
+ break;
+ case 4:
+ qspi_write32(priv->flags, &priv->regs->sfa2ad,
+ priv->amba_base[2]);
+ qspi_write32(priv->flags, &priv->regs->sfb1ad,
+ priv->amba_base[3]);
+ qspi_write32(priv->flags, &priv->regs->sfb2ad,
+ priv->amba_base[3] + amba_size_per_chip);
+ break;
+ default:
+ debug("Error: Unsupported chipselect number %u!\n",
+ priv->num_chipselect);
+ qspi_module_disable(priv, 1);
+ return -EINVAL;
+ }
qspi_set_lut(priv);
@@ -984,10 +1067,7 @@ static int fsl_qspi_probe(struct udevice *bus)
static int fsl_qspi_ofdata_to_platdata(struct udevice *bus)
{
- struct reg_data {
- u32 addr;
- u32 size;
- } regs_data[2];
+ struct fdt_resource res_regs, res_mem;
struct fsl_qspi_platdata *plat = bus->platdata;
const void *blob = gd->fdt_blob;
int node = bus->of_offset;
@@ -996,10 +1076,16 @@ static int fsl_qspi_ofdata_to_platdata(struct udevice *bus)
if (fdtdec_get_bool(blob, node, "big-endian"))
plat->flags |= QSPI_FLAG_REGMAP_ENDIAN_BIG;
- ret = fdtdec_get_int_array(blob, node, "reg", (u32 *)regs_data,
- sizeof(regs_data)/sizeof(u32));
+ ret = fdt_get_named_resource(blob, node, "reg", "reg-names",
+ "QuadSPI", &res_regs);
+ if (ret) {
+ debug("Error: can't get regs base addresses(ret = %d)!\n", ret);
+ return -ENOMEM;
+ }
+ ret = fdt_get_named_resource(blob, node, "reg", "reg-names",
+ "QuadSPI-memory", &res_mem);
if (ret) {
- debug("Error: can't get base addresses (ret = %d)!\n", ret);
+ debug("Error: can't get AMBA base addresses(ret = %d)!\n", ret);
return -ENOMEM;
}
@@ -1017,16 +1103,16 @@ static int fsl_qspi_ofdata_to_platdata(struct udevice *bus)
plat->num_chipselect = fdtdec_get_int(blob, node, "num-cs",
FSL_QSPI_MAX_CHIPSELECT_NUM);
- plat->reg_base = regs_data[0].addr;
- plat->amba_base = regs_data[1].addr;
- plat->amba_total_size = regs_data[1].size;
+ plat->reg_base = res_regs.start;
+ plat->amba_base = res_mem.start;
+ plat->amba_total_size = res_mem.end - res_mem.start + 1;
plat->flash_num = flash_num;
- debug("%s: regs=<0x%x> <0x%x, 0x%x>, max-frequency=%d, endianess=%s\n",
+ debug("%s: regs=<0x%llx> <0x%llx, 0x%llx>, max-frequency=%d, endianess=%s\n",
__func__,
- plat->reg_base,
- plat->amba_base,
- plat->amba_total_size,
+ (u64)plat->reg_base,
+ (u64)plat->amba_base,
+ (u64)plat->amba_total_size,
plat->speed_hz,
plat->flags & QSPI_FLAG_REGMAP_ENDIAN_BIG ? "be" : "le"
);
@@ -1055,8 +1141,7 @@ static int fsl_qspi_claim_bus(struct udevice *dev)
bus = dev->parent;
priv = dev_get_priv(bus);
- priv->cur_amba_base =
- priv->amba_base[0] + FSL_QSPI_FLASH_SIZE * slave_plat->cs;
+ priv->cur_amba_base = priv->amba_base[slave_plat->cs];
qspi_module_disable(priv, 0);
OpenPOWER on IntegriCloud