174803decSYouMin Chen // SPDX-License-Identifier: GPL-2.0
274803decSYouMin Chen /*
374803decSYouMin Chen * (C) Copyright 2018 Rockchip Electronics Co., Ltd.
474803decSYouMin Chen */
574803decSYouMin Chen
674803decSYouMin Chen #include <common.h>
774803decSYouMin Chen #include <ram.h>
874803decSYouMin Chen #include <asm/io.h>
9e1f97ec3SYouMin Chen #include <asm/arch/sdram.h>
105685f66aSYouMin Chen #include <asm/arch/sdram_common.h>
1174803decSYouMin Chen #include <asm/arch/sdram_phy_px30.h>
1274803decSYouMin Chen
sdram_phy_dll_bypass_set(void __iomem * phy_base,u32 freq)1374803decSYouMin Chen static void sdram_phy_dll_bypass_set(void __iomem *phy_base, u32 freq)
1474803decSYouMin Chen {
1574803decSYouMin Chen u32 tmp;
1674803decSYouMin Chen u32 i, j;
17*bbf5a1e4SYouMin Chen u32 dqs_dll_freq;
1874803decSYouMin Chen
1974803decSYouMin Chen setbits_le32(PHY_REG(phy_base, 0x13), 1 << 4);
2074803decSYouMin Chen clrbits_le32(PHY_REG(phy_base, 0x14), 1 << 3);
2174803decSYouMin Chen for (i = 0; i < 4; i++) {
2274803decSYouMin Chen j = 0x26 + i * 0x10;
2374803decSYouMin Chen setbits_le32(PHY_REG(phy_base, j), 1 << 4);
2474803decSYouMin Chen clrbits_le32(PHY_REG(phy_base, j + 0x1), 1 << 3);
2574803decSYouMin Chen }
2674803decSYouMin Chen
27*bbf5a1e4SYouMin Chen if (freq <= 400)
2874803decSYouMin Chen /* DLL bypass */
2974803decSYouMin Chen setbits_le32(PHY_REG(phy_base, 0xa4), 0x1f);
3074803decSYouMin Chen else
3174803decSYouMin Chen clrbits_le32(PHY_REG(phy_base, 0xa4), 0x1f);
3274803decSYouMin Chen
33*bbf5a1e4SYouMin Chen #ifdef CONFIG_ROCKCHIP_RK3328
34*bbf5a1e4SYouMin Chen dqs_dll_freq = 680;
35*bbf5a1e4SYouMin Chen #else
36*bbf5a1e4SYouMin Chen dqs_dll_freq = 801;
37*bbf5a1e4SYouMin Chen #endif
38*bbf5a1e4SYouMin Chen
39*bbf5a1e4SYouMin Chen if (freq <= dqs_dll_freq)
4074803decSYouMin Chen tmp = 2;
4174803decSYouMin Chen else
4274803decSYouMin Chen tmp = 1;
4374803decSYouMin Chen
4474803decSYouMin Chen for (i = 0; i < 4; i++) {
4574803decSYouMin Chen j = 0x28 + i * 0x10;
4674803decSYouMin Chen writel(tmp, PHY_REG(phy_base, j));
4774803decSYouMin Chen }
4874803decSYouMin Chen }
4974803decSYouMin Chen
sdram_phy_set_ds_odt(void __iomem * phy_base,u32 dram_type)5074803decSYouMin Chen static void sdram_phy_set_ds_odt(void __iomem *phy_base,
5174803decSYouMin Chen u32 dram_type)
5274803decSYouMin Chen {
5374803decSYouMin Chen u32 cmd_drv, clk_drv, dqs_drv, dqs_odt;
5474803decSYouMin Chen u32 i, j;
5574803decSYouMin Chen
5674803decSYouMin Chen if (dram_type == DDR3) {
5774803decSYouMin Chen cmd_drv = PHY_DDR3_RON_RTT_34ohm;
5874803decSYouMin Chen clk_drv = PHY_DDR3_RON_RTT_45ohm;
5974803decSYouMin Chen dqs_drv = PHY_DDR3_RON_RTT_34ohm;
6074803decSYouMin Chen dqs_odt = PHY_DDR3_RON_RTT_225ohm;
6174803decSYouMin Chen } else {
6274803decSYouMin Chen cmd_drv = PHY_DDR4_LPDDR3_RON_RTT_34ohm;
6374803decSYouMin Chen clk_drv = PHY_DDR4_LPDDR3_RON_RTT_43ohm;
6474803decSYouMin Chen dqs_drv = PHY_DDR4_LPDDR3_RON_RTT_34ohm;
6574803decSYouMin Chen if (dram_type == LPDDR2)
6674803decSYouMin Chen dqs_odt = PHY_DDR4_LPDDR3_RON_RTT_DISABLE;
6774803decSYouMin Chen else
6874803decSYouMin Chen dqs_odt = PHY_DDR4_LPDDR3_RON_RTT_240ohm;
6974803decSYouMin Chen }
7074803decSYouMin Chen /* DS */
7174803decSYouMin Chen writel(cmd_drv, PHY_REG(phy_base, 0x11));
7274803decSYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x12), 0x1f << 3, cmd_drv << 3);
7374803decSYouMin Chen writel(clk_drv, PHY_REG(phy_base, 0x16));
7474803decSYouMin Chen writel(clk_drv, PHY_REG(phy_base, 0x18));
7574803decSYouMin Chen
7674803decSYouMin Chen for (i = 0; i < 4; i++) {
7774803decSYouMin Chen j = 0x20 + i * 0x10;
7874803decSYouMin Chen writel(dqs_drv, PHY_REG(phy_base, j));
7974803decSYouMin Chen writel(dqs_drv, PHY_REG(phy_base, j + 0xf));
8074803decSYouMin Chen /* ODT */
8174803decSYouMin Chen writel(dqs_odt, PHY_REG(phy_base, j + 0x1));
8274803decSYouMin Chen writel(dqs_odt, PHY_REG(phy_base, j + 0xe));
8374803decSYouMin Chen }
8474803decSYouMin Chen }
8574803decSYouMin Chen
phy_soft_reset(void __iomem * phy_base)8674803decSYouMin Chen void phy_soft_reset(void __iomem *phy_base)
8774803decSYouMin Chen {
8874803decSYouMin Chen clrbits_le32(PHY_REG(phy_base, 0), 0x3 << 2);
8974803decSYouMin Chen udelay(1);
9074803decSYouMin Chen setbits_le32(PHY_REG(phy_base, 0), ANALOG_DERESET);
9174803decSYouMin Chen udelay(5);
9274803decSYouMin Chen setbits_le32(PHY_REG(phy_base, 0), DIGITAL_DERESET);
9374803decSYouMin Chen udelay(1);
9474803decSYouMin Chen }
9574803decSYouMin Chen
phy_dram_set_bw(void __iomem * phy_base,u32 bw)9674803decSYouMin Chen void phy_dram_set_bw(void __iomem *phy_base, u32 bw)
9774803decSYouMin Chen {
9874803decSYouMin Chen if (bw == 2) {
9974803decSYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 0xf << 4);
10074803decSYouMin Chen setbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
10174803decSYouMin Chen setbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
10274803decSYouMin Chen } else if (bw == 1) {
10374803decSYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 3 << 4);
10474803decSYouMin Chen clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
10574803decSYouMin Chen clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
10674803decSYouMin Chen } else if (bw == 0) {
10774803decSYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 1 << 4);
10874803decSYouMin Chen clrbits_le32(PHY_REG(phy_base, 0x36), 1 << 3);
10974803decSYouMin Chen clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
11074803decSYouMin Chen clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
11174803decSYouMin Chen }
11274803decSYouMin Chen
11374803decSYouMin Chen phy_soft_reset(phy_base);
11474803decSYouMin Chen }
11574803decSYouMin Chen
phy_data_training(void __iomem * phy_base,u32 cs,u32 dramtype)11674803decSYouMin Chen int phy_data_training(void __iomem *phy_base, u32 cs, u32 dramtype)
11774803decSYouMin Chen {
11874803decSYouMin Chen u32 ret;
11974803decSYouMin Chen u32 odt_val;
12074803decSYouMin Chen u32 i, j;
12174803decSYouMin Chen
12274803decSYouMin Chen odt_val = readl(PHY_REG(phy_base, 0x2e));
12374803decSYouMin Chen
12474803decSYouMin Chen for (i = 0; i < 4; i++) {
12574803decSYouMin Chen j = 0x20 + i * 0x10;
12674803decSYouMin Chen writel(PHY_DDR3_RON_RTT_225ohm, PHY_REG(phy_base, j + 0x1));
12774803decSYouMin Chen writel(0, PHY_REG(phy_base, j + 0xe));
12874803decSYouMin Chen }
12974803decSYouMin Chen
13074803decSYouMin Chen if (dramtype == DDR4) {
13174803decSYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x29), 0x3, 0);
13274803decSYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x39), 0x3, 0);
13374803decSYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x49), 0x3, 0);
13474803decSYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x59), 0x3, 0);
13574803decSYouMin Chen }
13674803decSYouMin Chen /* choose training cs */
13774803decSYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs));
13874803decSYouMin Chen /* enable gate training */
13974803decSYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 1);
14074803decSYouMin Chen udelay(50);
14174803decSYouMin Chen ret = readl(PHY_REG(phy_base, 0xff));
14274803decSYouMin Chen /* disable gate training */
14374803decSYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 0);
144*bbf5a1e4SYouMin Chen #ifndef CONFIG_ROCKCHIP_RK3328
14574803decSYouMin Chen clrbits_le32(PHY_REG(phy_base, 2), 0x30);
146*bbf5a1e4SYouMin Chen #endif
14774803decSYouMin Chen
14874803decSYouMin Chen if (dramtype == DDR4) {
14974803decSYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x29), 0x3, 0x2);
15074803decSYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x39), 0x3, 0x2);
15174803decSYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x49), 0x3, 0x2);
15274803decSYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0x59), 0x3, 0x2);
15374803decSYouMin Chen }
15474803decSYouMin Chen
15574803decSYouMin Chen if (ret & 0x10) {
15674803decSYouMin Chen ret = -1;
15774803decSYouMin Chen } else {
15874803decSYouMin Chen ret = (ret & 0xf) ^ (readl(PHY_REG(phy_base, 0)) >> 4);
15974803decSYouMin Chen ret = (ret == 0) ? 0 : -1;
16074803decSYouMin Chen }
16174803decSYouMin Chen
16274803decSYouMin Chen for (i = 0; i < 4; i++) {
16374803decSYouMin Chen j = 0x20 + i * 0x10;
16474803decSYouMin Chen writel(odt_val, PHY_REG(phy_base, j + 0x1));
16574803decSYouMin Chen writel(odt_val, PHY_REG(phy_base, j + 0xe));
16674803decSYouMin Chen }
16774803decSYouMin Chen return ret;
16874803decSYouMin Chen }
16974803decSYouMin Chen
phy_cfg(void __iomem * phy_base,struct ddr_phy_regs * phy_regs,struct ddr_phy_skew * skew,struct sdram_base_params * base,u32 bw)17074803decSYouMin Chen void phy_cfg(void __iomem *phy_base,
17174803decSYouMin Chen struct ddr_phy_regs *phy_regs, struct ddr_phy_skew *skew,
17274803decSYouMin Chen struct sdram_base_params *base, u32 bw)
17374803decSYouMin Chen {
17474803decSYouMin Chen u32 i;
17574803decSYouMin Chen
17674803decSYouMin Chen sdram_phy_dll_bypass_set(phy_base, base->ddr_freq);
17774803decSYouMin Chen for (i = 0; phy_regs->phy[i][0] != 0xFFFFFFFF; i++) {
17874803decSYouMin Chen writel(phy_regs->phy[i][1],
17974803decSYouMin Chen phy_base + phy_regs->phy[i][0]);
18074803decSYouMin Chen }
18174803decSYouMin Chen if (bw == 2) {
18274803decSYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 0xf << 4);
18374803decSYouMin Chen } else if (bw == 1) {
18474803decSYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 3 << 4);
18574803decSYouMin Chen /* disable DQS2,DQS3 tx dll for saving power */
18674803decSYouMin Chen clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
18774803decSYouMin Chen clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
18874803decSYouMin Chen } else {
18974803decSYouMin Chen clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 1 << 4);
19074803decSYouMin Chen /* disable DQS2,DQS3 tx dll for saving power */
19174803decSYouMin Chen clrbits_le32(PHY_REG(phy_base, 0x36), 1 << 3);
19274803decSYouMin Chen clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
19374803decSYouMin Chen clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
19474803decSYouMin Chen }
19574803decSYouMin Chen sdram_phy_set_ds_odt(phy_base, base->dramtype);
19674803decSYouMin Chen
19774803decSYouMin Chen /* deskew */
19874803decSYouMin Chen setbits_le32(PHY_REG(phy_base, 2), 8);
19974803decSYouMin Chen sdram_copy_to_reg(PHY_REG(phy_base, 0xb0),
20074803decSYouMin Chen &skew->a0_a1_skew[0], 15 * 4);
20174803decSYouMin Chen sdram_copy_to_reg(PHY_REG(phy_base, 0x70),
20274803decSYouMin Chen &skew->cs0_dm0_skew[0], 44 * 4);
20374803decSYouMin Chen sdram_copy_to_reg(PHY_REG(phy_base, 0xc0),
20474803decSYouMin Chen &skew->cs1_dm0_skew[0], 44 * 4);
20574803decSYouMin Chen }
20674803decSYouMin Chen
207