mirror of
https://gitee.com/Vancouver2017/luban-lite-t3e-pro.git
synced 2025-12-14 02:18:54 +00:00
111 lines
2.5 KiB
C
111 lines
2.5 KiB
C
/*
|
|
* Copyright (c) 2024, ArtInChip Technology Co., Ltd
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Authors: Jiji Chen <jiji.chen@artinchip.com>
|
|
*/
|
|
|
|
#include <rtconfig.h>
|
|
#include <stdbool.h>
|
|
#include <string.h>
|
|
#include <stdint.h>
|
|
#include <aic_core.h>
|
|
#include <hal_qspi.h>
|
|
#include "qspi_internal.h"
|
|
|
|
void qspi_reg_dump(u32 base)
|
|
{
|
|
u32 *p, i;
|
|
|
|
p = (void *)(unsigned long)base;
|
|
for (i = 0; i < 40; i++) {
|
|
if (i % 4 == 0)
|
|
printf("\n0x%lX : ", (unsigned long)p);
|
|
printf("%08X ", *p);
|
|
p++;
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
void show_freq(char *msg, u32 id, u32 hz)
|
|
{
|
|
printf("qspi%d %s: %dHz\n", id, msg, hz);
|
|
}
|
|
|
|
u32 qspi_calc_timeout(u32 bus_hz, u32 len)
|
|
{
|
|
u32 tmo_cnt, tmo_us;
|
|
u32 tmo_speed = 100;
|
|
|
|
if (bus_hz < HAL_QSPI_MIN_FREQ_HZ)
|
|
tmo_us = (1000000 * len * 8) / bus_hz;
|
|
else if (bus_hz < 1000000)
|
|
tmo_us = (1000 * len * 8) / (bus_hz / 1000);
|
|
else
|
|
tmo_us = (len * 8) / (bus_hz / 1000000);
|
|
|
|
/* Add 100ms time padding */
|
|
tmo_us += 100000;
|
|
tmo_cnt = tmo_us / HAL_QSPI_WAIT_PER_CYCLE;
|
|
|
|
/* Consider the speed limit of DMA or CPU copy.
|
|
*/
|
|
if (len >= QSPI_TRANSFER_DATA_LEN_1M)
|
|
tmo_speed = ((len / QSPI_CPU_DMA_MIN_SPEED_MS) + 1) * 1000;
|
|
|
|
return max(tmo_cnt, tmo_speed);
|
|
}
|
|
|
|
u32 qspi_master_get_best_div_param(u32 sclk, u32 bus_hz, u32 *div)
|
|
{
|
|
u32 cdr1_clk, cdr2_clk;
|
|
int cdr2, cdr1;
|
|
|
|
/* Get the best cdr1 param if going to use cdr1 */
|
|
cdr1 = 0;
|
|
while ((sclk >> cdr1) > bus_hz)
|
|
cdr1++;
|
|
if (cdr1 > 0xF)
|
|
cdr1 = 0xF;
|
|
|
|
/* Get the best cdr2 param if going to use cdr2 */
|
|
cdr2 = (int)(sclk / (bus_hz * 2)) - 1;
|
|
if (cdr2 < 0)
|
|
cdr2 = 0;
|
|
if (cdr2 > 0xFF)
|
|
cdr2 = 0xFF;
|
|
cdr2_clk = sclk / (2 * cdr2 + 1);
|
|
|
|
cdr1_clk = sclk >> cdr1;
|
|
cdr2_clk = sclk / (2 * cdr2 + 1);
|
|
|
|
/* cdr1 param vs cdr2 param, use the best */
|
|
if (cdr1_clk == bus_hz) {
|
|
*div = cdr1;
|
|
return 0;
|
|
} else if (cdr2_clk == bus_hz) {
|
|
*div = cdr2;
|
|
return 1;
|
|
} else if ((cdr2_clk < bus_hz) && (cdr1_clk < bus_hz)) {
|
|
/* Two clks less than expect clk, use the larger one */
|
|
if (cdr2_clk > cdr1_clk) {
|
|
*div = cdr2;
|
|
return 1;
|
|
}
|
|
*div = cdr1;
|
|
return 0;
|
|
}
|
|
/*
|
|
* 1. Two clks great than expect clk, use least one
|
|
* 2. There is one clk less than expect clk, use it
|
|
*/
|
|
if (cdr2_clk < cdr1_clk) {
|
|
*div = cdr2;
|
|
return 1;
|
|
}
|
|
*div = cdr1;
|
|
return 0;
|
|
}
|
|
|