drivers: rkflash: Enable DLL tuning

1.Support after SFC ver 4
2.If the io rate is high than 100MHz, enable SFC delay line in
default
3.Get id byte as data pattern

Change-Id: Ia405771c0bc94eddaa45e1d85c7fa10a85c40531
Signed-off-by: Jon Lin <jon.lin@rock-chips.com>
This commit is contained in:
Jon Lin
2021-03-28 17:27:23 +08:00
committed by Tao Huang
parent b30f443cdf
commit f90bf3cdf2

View File

@@ -22,8 +22,9 @@
#include "rkflash_api.h"
#include "rkflash_blk.h"
#define RKSFC_VERSION_AND_DATE "rksfc_base v1.1 2016-01-08"
#define RKSFC_CLK_MAX_RATE (150 * 1000 * 1000)
#define RKSFC_VERSION_AND_DATE "rksfc_base v1.1 2016-01-08"
#define RKSFC_CLK_MAX_RATE (150 * 1000 * 1000)
#define RKSFC_DLL_THRESHOLD_RATE (100 * 1000 * 1000)
struct rksfc_info {
void __iomem *reg_base;
@@ -31,6 +32,7 @@ struct rksfc_info {
int clk_rate;
struct clk *clk; /* sfc clk*/
struct clk *ahb_clk; /* ahb clk gate*/
u16 dll_cells;
};
static struct rksfc_info g_sfc_info;
@@ -102,6 +104,45 @@ static int rksfc_irq_deinit(void)
return 0;
}
static void rksfc_delay_lines_tuning(void)
{
u8 id[3], id_temp[3];
int right, left = -1;
struct rk_sfc_op op;
u16 cell_max = SCLK_SMP_SEL_MAX_V4;
if (sfc_get_version() >= SFC_VER_5)
cell_max = SCLK_SMP_SEL_MAX_V5;
op.sfcmd.d32 = 0;
op.sfcmd.b.cmd = 0x9F;
op.sfctrl.d32 = 0;
clk_set_rate(g_sfc_info.clk, RKSFC_DLL_THRESHOLD_RATE);
sfc_request(&op, 0, id, 3);
clk_set_rate(g_sfc_info.clk, g_sfc_info.clk_rate);
for (right = 10; right <= cell_max; right += 10) {
sfc_set_delay_lines((u16)right);
sfc_request(&op, 0, id_temp, 3);
if (left == -1 && !memcmp(&id, &id_temp, 3))
left = right;
else if (left >= 0 && memcmp(&id, &id_temp, 3))
break;
}
if (left >= 0 && (right - left > 50)) {
g_sfc_info.dll_cells = (u16)(right + left) / 2;
sfc_set_delay_lines(g_sfc_info.dll_cells);
} else {
g_sfc_info.dll_cells = 0;
sfc_disable_delay_lines();
clk_set_rate(g_sfc_info.clk, RKSFC_DLL_THRESHOLD_RATE);
g_sfc_info.clk_rate = clk_get_rate(g_sfc_info.clk);
}
pr_info("%s clk rate = %d\n", __func__, g_sfc_info.clk_rate);
}
static int rksfc_probe(struct platform_device *pdev)
{
int irq;
@@ -153,6 +194,14 @@ static int rksfc_probe(struct platform_device *pdev)
500 * USEC_PER_MSEC))
dev_err(g_sfc_dev, "Wait for SFC idle timeout!\n");
#endif
sfc_init(g_sfc_info.reg_base);
if (sfc_get_version() >= SFC_VER_4 &&
g_sfc_info.clk_rate > RKSFC_DLL_THRESHOLD_RATE)
rksfc_delay_lines_tuning();
else if (sfc_get_version() >= SFC_VER_4)
sfc_disable_delay_lines();
#ifdef CONFIG_RK_SFC_NOR
dev_result = rkflash_dev_init(g_sfc_info.reg_base, FLASH_TYPE_SFC_NOR, &sfc_nor_ops);
#endif
@@ -171,6 +220,8 @@ static int __maybe_unused rksfc_suspend(struct device *dev)
static int __maybe_unused rksfc_resume(struct device *dev)
{
if (g_sfc_info.dll_cells)
sfc_set_delay_lines(g_sfc_info.dll_cells);
return rkflash_dev_resume(g_sfc_info.reg_base);
}