ram: rockchip: add phy driver code for PX30
This sdram_phy_px30.c is based on PX30 SoC, the functions are common for phy, other SoCs with similar hardware could re-use it. Signed-off-by: YouMin Chen <cym@rock-chips.com> Signed-off-by: Kever Yang <kever.yang@rock-chips.com>
This commit is contained in:
parent
09d7872336
commit
691368c7f7
62
arch/arm/include/asm/arch-rockchip/sdram_phy_px30.h
Normal file
62
arch/arm/include/asm/arch-rockchip/sdram_phy_px30.h
Normal file
@ -0,0 +1,62 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2018 Rockchip Electronics Co., Ltd
|
||||
*/
|
||||
|
||||
#ifndef _ASM_ARCH_SDRAM_PHY_PX30_H
|
||||
#define _ASM_ARCH_SDRAM_PHY_PX30_H
|
||||
#include <asm/arch-rockchip/sdram_common.h>
|
||||
#include <asm/arch-rockchip/sdram_phy_ron_rtt_px30.h>
|
||||
|
||||
struct ddr_phy_regs {
|
||||
u32 phy[5][2];
|
||||
};
|
||||
|
||||
#define PHY_REG(base, n) ((base) + 4 * (n))
|
||||
|
||||
/* PHY_REG0 */
|
||||
#define DIGITAL_DERESET BIT(3)
|
||||
#define ANALOG_DERESET BIT(2)
|
||||
#define DIGITAL_RESET (0 << 3)
|
||||
#define ANALOG_RESET (0 << 2)
|
||||
|
||||
/* PHY_REG1 */
|
||||
#define PHY_DDR2 (0)
|
||||
#define PHY_LPDDR2 (1)
|
||||
#define PHY_DDR3 (2)
|
||||
#define PHY_LPDDR3 (3)
|
||||
#define PHY_DDR4 (4)
|
||||
#define PHY_BL_4 (0 << 2)
|
||||
#define PHY_BL_8 BIT(2)
|
||||
|
||||
/* PHY_REG2 */
|
||||
#define PHY_DTT_EN BIT(0)
|
||||
#define PHY_DTT_DISB (0 << 0)
|
||||
#define PHY_WRITE_LEVELING_EN BIT(2)
|
||||
#define PHY_WRITE_LEVELING_DISB (0 << 2)
|
||||
#define PHY_SELECT_CS0 (2)
|
||||
#define PHY_SELECT_CS1 (1)
|
||||
#define PHY_SELECT_CS0_1 (0)
|
||||
#define PHY_WRITE_LEVELING_SELECTCS(n) ((n) << 6)
|
||||
#define PHY_DATA_TRAINING_SELECTCS(n) ((n) << 4)
|
||||
|
||||
struct ddr_phy_skew {
|
||||
u32 a0_a1_skew[15];
|
||||
u32 cs0_dm0_skew[11];
|
||||
u32 cs0_dm1_skew[11];
|
||||
u32 cs0_dm2_skew[11];
|
||||
u32 cs0_dm3_skew[11];
|
||||
u32 cs1_dm0_skew[11];
|
||||
u32 cs1_dm1_skew[11];
|
||||
u32 cs1_dm2_skew[11];
|
||||
u32 cs1_dm3_skew[11];
|
||||
};
|
||||
|
||||
void phy_soft_reset(void __iomem *phy_base);
|
||||
void phy_dram_set_bw(void __iomem *phy_base, u32 bw);
|
||||
void phy_cfg(void __iomem *phy_base,
|
||||
struct ddr_phy_regs *phy_regs, struct ddr_phy_skew *skew,
|
||||
struct sdram_base_params *base, u32 bw);
|
||||
int phy_data_training(void __iomem *phy_base, u32 cs, u32 dramtype);
|
||||
|
||||
#endif
|
59
arch/arm/include/asm/arch-rockchip/sdram_phy_ron_rtt_px30.h
Normal file
59
arch/arm/include/asm/arch-rockchip/sdram_phy_ron_rtt_px30.h
Normal file
@ -0,0 +1,59 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2018 Rockchip Electronics Co., Ltd
|
||||
*/
|
||||
|
||||
#ifndef _ASM_ARCH_SDRAM_PHY_RON_RTT_PX30_H
|
||||
#define _ASM_ARCH_SDRAM_PHY_RON_RTT_PX30_H
|
||||
|
||||
#define PHY_DDR3_RON_RTT_DISABLE (0)
|
||||
#define PHY_DDR3_RON_RTT_451ohm (1)
|
||||
#define PHY_DDR3_RON_RTT_225ohm (2)
|
||||
#define PHY_DDR3_RON_RTT_150ohm (3)
|
||||
#define PHY_DDR3_RON_RTT_112ohm (4)
|
||||
#define PHY_DDR3_RON_RTT_90ohm (5)
|
||||
#define PHY_DDR3_RON_RTT_75ohm (6)
|
||||
#define PHY_DDR3_RON_RTT_64ohm (7)
|
||||
#define PHY_DDR3_RON_RTT_56ohm (16)
|
||||
#define PHY_DDR3_RON_RTT_50ohm (17)
|
||||
#define PHY_DDR3_RON_RTT_45ohm (18)
|
||||
#define PHY_DDR3_RON_RTT_41ohm (19)
|
||||
#define PHY_DDR3_RON_RTT_37ohm (20)
|
||||
#define PHY_DDR3_RON_RTT_34ohm (21)
|
||||
#define PHY_DDR3_RON_RTT_33ohm (22)
|
||||
#define PHY_DDR3_RON_RTT_30ohm (23)
|
||||
#define PHY_DDR3_RON_RTT_28ohm (24)
|
||||
#define PHY_DDR3_RON_RTT_26ohm (25)
|
||||
#define PHY_DDR3_RON_RTT_25ohm (26)
|
||||
#define PHY_DDR3_RON_RTT_23ohm (27)
|
||||
#define PHY_DDR3_RON_RTT_22ohm (28)
|
||||
#define PHY_DDR3_RON_RTT_21ohm (29)
|
||||
#define PHY_DDR3_RON_RTT_20ohm (30)
|
||||
#define PHY_DDR3_RON_RTT_19ohm (31)
|
||||
|
||||
#define PHY_DDR4_LPDDR3_RON_RTT_DISABLE (0)
|
||||
#define PHY_DDR4_LPDDR3_RON_RTT_480ohm (1)
|
||||
#define PHY_DDR4_LPDDR3_RON_RTT_240ohm (2)
|
||||
#define PHY_DDR4_LPDDR3_RON_RTT_160ohm (3)
|
||||
#define PHY_DDR4_LPDDR3_RON_RTT_120ohm (4)
|
||||
#define PHY_DDR4_LPDDR3_RON_RTT_96ohm (5)
|
||||
#define PHY_DDR4_LPDDR3_RON_RTT_80ohm (6)
|
||||
#define PHY_DDR4_LPDDR3_RON_RTT_68ohm (7)
|
||||
#define PHY_DDR4_LPDDR3_RON_RTT_60ohm (16)
|
||||
#define PHY_DDR4_LPDDR3_RON_RTT_53ohm (17)
|
||||
#define PHY_DDR4_LPDDR3_RON_RTT_48ohm (18)
|
||||
#define PHY_DDR4_LPDDR3_RON_RTT_43ohm (19)
|
||||
#define PHY_DDR4_LPDDR3_RON_RTT_40ohm (20)
|
||||
#define PHY_DDR4_LPDDR3_RON_RTT_37ohm (21)
|
||||
#define PHY_DDR4_LPDDR3_RON_RTT_34ohm (22)
|
||||
#define PHY_DDR4_LPDDR3_RON_RTT_32ohm (23)
|
||||
#define PHY_DDR4_LPDDR3_RON_RTT_30ohm (24)
|
||||
#define PHY_DDR4_LPDDR3_RON_RTT_28ohm (25)
|
||||
#define PHY_DDR4_LPDDR3_RON_RTT_26ohm (26)
|
||||
#define PHY_DDR4_LPDDR3_RON_RTT_25ohm (27)
|
||||
#define PHY_DDR4_LPDDR3_RON_RTT_24ohm (28)
|
||||
#define PHY_DDR4_LPDDR3_RON_RTT_22ohm (29)
|
||||
#define PHY_DDR4_LPDDR3_RON_RTT_21ohm (30)
|
||||
#define PHY_DDR4_LPDDR3_RON_RTT_20ohm (31)
|
||||
|
||||
#endif
|
205
drivers/ram/rockchip/sdram_phy_px30.c
Normal file
205
drivers/ram/rockchip/sdram_phy_px30.c
Normal file
@ -0,0 +1,205 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* (C) Copyright 2018 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <ram.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch-rockchip/sdram.h>
|
||||
#include <asm/arch-rockchip/sdram_common.h>
|
||||
#include <asm/arch-rockchip/sdram_phy_px30.h>
|
||||
|
||||
static void sdram_phy_dll_bypass_set(void __iomem *phy_base, u32 freq)
|
||||
{
|
||||
u32 tmp;
|
||||
u32 i, j;
|
||||
u32 dqs_dll_freq;
|
||||
|
||||
setbits_le32(PHY_REG(phy_base, 0x13), 1 << 4);
|
||||
clrbits_le32(PHY_REG(phy_base, 0x14), 1 << 3);
|
||||
for (i = 0; i < 4; i++) {
|
||||
j = 0x26 + i * 0x10;
|
||||
setbits_le32(PHY_REG(phy_base, j), 1 << 4);
|
||||
clrbits_le32(PHY_REG(phy_base, j + 0x1), 1 << 3);
|
||||
}
|
||||
|
||||
if (freq <= 400)
|
||||
/* DLL bypass */
|
||||
setbits_le32(PHY_REG(phy_base, 0xa4), 0x1f);
|
||||
else
|
||||
clrbits_le32(PHY_REG(phy_base, 0xa4), 0x1f);
|
||||
|
||||
#ifdef CONFIG_ROCKCHIP_RK3328
|
||||
dqs_dll_freq = 680;
|
||||
#else
|
||||
dqs_dll_freq = 801;
|
||||
#endif
|
||||
|
||||
if (freq <= dqs_dll_freq)
|
||||
tmp = 2;
|
||||
else
|
||||
tmp = 1;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
j = 0x28 + i * 0x10;
|
||||
writel(tmp, PHY_REG(phy_base, j));
|
||||
}
|
||||
}
|
||||
|
||||
static void sdram_phy_set_ds_odt(void __iomem *phy_base,
|
||||
u32 dram_type)
|
||||
{
|
||||
u32 cmd_drv, clk_drv, dqs_drv, dqs_odt;
|
||||
u32 i, j;
|
||||
|
||||
if (dram_type == DDR3) {
|
||||
cmd_drv = PHY_DDR3_RON_RTT_34ohm;
|
||||
clk_drv = PHY_DDR3_RON_RTT_45ohm;
|
||||
dqs_drv = PHY_DDR3_RON_RTT_34ohm;
|
||||
dqs_odt = PHY_DDR3_RON_RTT_225ohm;
|
||||
} else {
|
||||
cmd_drv = PHY_DDR4_LPDDR3_RON_RTT_34ohm;
|
||||
clk_drv = PHY_DDR4_LPDDR3_RON_RTT_43ohm;
|
||||
dqs_drv = PHY_DDR4_LPDDR3_RON_RTT_34ohm;
|
||||
if (dram_type == LPDDR2)
|
||||
dqs_odt = PHY_DDR4_LPDDR3_RON_RTT_DISABLE;
|
||||
else
|
||||
dqs_odt = PHY_DDR4_LPDDR3_RON_RTT_240ohm;
|
||||
}
|
||||
/* DS */
|
||||
writel(cmd_drv, PHY_REG(phy_base, 0x11));
|
||||
clrsetbits_le32(PHY_REG(phy_base, 0x12), 0x1f << 3, cmd_drv << 3);
|
||||
writel(clk_drv, PHY_REG(phy_base, 0x16));
|
||||
writel(clk_drv, PHY_REG(phy_base, 0x18));
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
j = 0x20 + i * 0x10;
|
||||
writel(dqs_drv, PHY_REG(phy_base, j));
|
||||
writel(dqs_drv, PHY_REG(phy_base, j + 0xf));
|
||||
/* ODT */
|
||||
writel(dqs_odt, PHY_REG(phy_base, j + 0x1));
|
||||
writel(dqs_odt, PHY_REG(phy_base, j + 0xe));
|
||||
}
|
||||
}
|
||||
|
||||
void phy_soft_reset(void __iomem *phy_base)
|
||||
{
|
||||
clrbits_le32(PHY_REG(phy_base, 0), 0x3 << 2);
|
||||
udelay(1);
|
||||
setbits_le32(PHY_REG(phy_base, 0), ANALOG_DERESET);
|
||||
udelay(5);
|
||||
setbits_le32(PHY_REG(phy_base, 0), DIGITAL_DERESET);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
void phy_dram_set_bw(void __iomem *phy_base, u32 bw)
|
||||
{
|
||||
if (bw == 2) {
|
||||
clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 0xf << 4);
|
||||
setbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
|
||||
setbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
|
||||
} else if (bw == 1) {
|
||||
clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 3 << 4);
|
||||
clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
|
||||
clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
|
||||
} else if (bw == 0) {
|
||||
clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 1 << 4);
|
||||
clrbits_le32(PHY_REG(phy_base, 0x36), 1 << 3);
|
||||
clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
|
||||
clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
|
||||
}
|
||||
|
||||
phy_soft_reset(phy_base);
|
||||
}
|
||||
|
||||
int phy_data_training(void __iomem *phy_base, u32 cs, u32 dramtype)
|
||||
{
|
||||
u32 ret;
|
||||
u32 odt_val;
|
||||
u32 i, j;
|
||||
|
||||
odt_val = readl(PHY_REG(phy_base, 0x2e));
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
j = 0x20 + i * 0x10;
|
||||
writel(PHY_DDR3_RON_RTT_225ohm, PHY_REG(phy_base, j + 0x1));
|
||||
writel(0, PHY_REG(phy_base, j + 0xe));
|
||||
}
|
||||
|
||||
if (dramtype == DDR4) {
|
||||
clrsetbits_le32(PHY_REG(phy_base, 0x29), 0x3, 0);
|
||||
clrsetbits_le32(PHY_REG(phy_base, 0x39), 0x3, 0);
|
||||
clrsetbits_le32(PHY_REG(phy_base, 0x49), 0x3, 0);
|
||||
clrsetbits_le32(PHY_REG(phy_base, 0x59), 0x3, 0);
|
||||
}
|
||||
/* choose training cs */
|
||||
clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs));
|
||||
/* enable gate training */
|
||||
clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 1);
|
||||
udelay(50);
|
||||
ret = readl(PHY_REG(phy_base, 0xff));
|
||||
/* disable gate training */
|
||||
clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 0);
|
||||
#ifndef CONFIG_ROCKCHIP_RK3328
|
||||
clrbits_le32(PHY_REG(phy_base, 2), 0x30);
|
||||
#endif
|
||||
|
||||
if (dramtype == DDR4) {
|
||||
clrsetbits_le32(PHY_REG(phy_base, 0x29), 0x3, 0x2);
|
||||
clrsetbits_le32(PHY_REG(phy_base, 0x39), 0x3, 0x2);
|
||||
clrsetbits_le32(PHY_REG(phy_base, 0x49), 0x3, 0x2);
|
||||
clrsetbits_le32(PHY_REG(phy_base, 0x59), 0x3, 0x2);
|
||||
}
|
||||
|
||||
if (ret & 0x10) {
|
||||
ret = -1;
|
||||
} else {
|
||||
ret = (ret & 0xf) ^ (readl(PHY_REG(phy_base, 0)) >> 4);
|
||||
ret = (ret == 0) ? 0 : -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
j = 0x20 + i * 0x10;
|
||||
writel(odt_val, PHY_REG(phy_base, j + 0x1));
|
||||
writel(odt_val, PHY_REG(phy_base, j + 0xe));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void phy_cfg(void __iomem *phy_base,
|
||||
struct ddr_phy_regs *phy_regs, struct ddr_phy_skew *skew,
|
||||
struct sdram_base_params *base, u32 bw)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
sdram_phy_dll_bypass_set(phy_base, base->ddr_freq);
|
||||
for (i = 0; phy_regs->phy[i][0] != 0xFFFFFFFF; i++) {
|
||||
writel(phy_regs->phy[i][1],
|
||||
phy_base + phy_regs->phy[i][0]);
|
||||
}
|
||||
if (bw == 2) {
|
||||
clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 0xf << 4);
|
||||
} else if (bw == 1) {
|
||||
clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 3 << 4);
|
||||
/* disable DQS2,DQS3 tx dll for saving power */
|
||||
clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
|
||||
clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
|
||||
} else {
|
||||
clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 1 << 4);
|
||||
/* disable DQS2,DQS3 tx dll for saving power */
|
||||
clrbits_le32(PHY_REG(phy_base, 0x36), 1 << 3);
|
||||
clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
|
||||
clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
|
||||
}
|
||||
sdram_phy_set_ds_odt(phy_base, base->dramtype);
|
||||
|
||||
/* deskew */
|
||||
setbits_le32(PHY_REG(phy_base, 2), 8);
|
||||
sdram_copy_to_reg(PHY_REG(phy_base, 0xb0),
|
||||
&skew->a0_a1_skew[0], 15 * 4);
|
||||
sdram_copy_to_reg(PHY_REG(phy_base, 0x70),
|
||||
&skew->cs0_dm0_skew[0], 44 * 4);
|
||||
sdram_copy_to_reg(PHY_REG(phy_base, 0xc0),
|
||||
&skew->cs1_dm0_skew[0], 44 * 4);
|
||||
}
|
Loading…
Reference in New Issue
Block a user