mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
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:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user