From patchwork Tue Jul 16 11:57:31 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jagan Teki X-Patchwork-Id: 792 Return-Path: X-Original-To: linux-amarula@patchwork.amarulasolutions.com Delivered-To: linux-amarula@patchwork.amarulasolutions.com Received: from mail-pg1-f199.google.com (mail-pg1-f199.google.com [209.85.215.199]) by ganimede.amarulasolutions.com (Postfix) with ESMTPS id CC1C63F08F for ; Tue, 16 Jul 2019 14:00:31 +0200 (CEST) Received: by mail-pg1-f199.google.com with SMTP id m17sf3565954pgh.21 for ; Tue, 16 Jul 2019 05:00:31 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1563278430; cv=pass; d=google.com; s=arc-20160816; b=L0ljKCRk2dNCACyShZZIUvhbsmShtzE8ltQoLUS6LuSU+57HVHZWcMXU/gMWxapVw1 nPBN/FQKRzq19gl9bAtC6te1PqdQFOOwCH10m5akaFyOMEykIrV/wMHcTQ6cDGObkCBu CpCUcbFQdMY7h77Hz0Smty45pyNynFc15FbKM4UPLZ+TOwU6NGVh+DVOnF1jjk01uQHo FBFhILjbSlfdsfH/hHl5i6czu9jcj7REJhWOzbBeO/BrvUOiJ5hbOzhv4eX2bSw4giLp 5lKc8fKHdDCqA3AbF6vlmvX7I0aEsEM9Ior/1x89E+bjRRbQ9GP3HyRO7DQyfw76/uWV ARnw== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-unsubscribe:list-archive:list-help:list-post:list-id :mailing-list:precedence:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=WTImTGXZkCrVJ5J8B9P1bF1u5QoVR6Yw0eQZVI+EvUE=; b=MLRvt0/kfe3rKp3A5UGAB8ymOQTg1RDaOM3ohh+1jB9L0ttGKgTkFOXY2Q2XtFtP4n MaGTSzIFqCeX6yrmVwRx5dDSAScb8dbyukFIL37dpodk9Ob5szVkc1uoo72Dj144f/TO rc5bLddVMK+3DFT1D/iCvUhbAcFNs+LZd4Z1nqX3+A7bNANQkYmy3A2hAP1uV38hT1Lr C55b1Ri+1Cul/++nXuiZ8/MwSQxPyMu1yI3LZP+785+WhEzyZsgePDVHZyyrbQE+cElK BwOfwS1Ge9BVBXs1iLpIPQPBSfDYxVIvv5w/XkaLJu33BD5m/2wCW2teFJMCNvjVNPTd g1yQ== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@amarulasolutions.com header.s=google header.b=K3lhGmSn; spf=pass (google.com: domain of jagan@amarulasolutions.com designates 209.85.220.65 as permitted sender) smtp.mailfrom=jagan@amarulasolutions.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amarulasolutions.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:x-original-sender:x-original-authentication-results :precedence:mailing-list:list-id:list-post:list-help:list-archive :list-unsubscribe; bh=WTImTGXZkCrVJ5J8B9P1bF1u5QoVR6Yw0eQZVI+EvUE=; b=B7uhgbCfP6ysDuH3h1zZgchQGHU1k/Z1sFZFszucbzsoYfH+Zka44uhsBHwdE4Mie/ InYwQMlZkkpA1qn2MfWFAW5NRJ24UMGBZ3jIE/kKANMT1Cfp6Mmq21bWsR3CKtXLMVKI RDoyU69sBqlRe77edoSM6CiqP+9TcsAYskqOA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :x-spam-checked-in-group:list-post:list-help:list-archive :list-unsubscribe; bh=WTImTGXZkCrVJ5J8B9P1bF1u5QoVR6Yw0eQZVI+EvUE=; b=HN2+MvJFuBTtZCCMMxgQH+VBNMWp/gi91suWTJEAM1HNVcazzRXKcAVlBJwaWrhIli CiNJkLnOYakxoEsdd867AfERlTLZHC8qfpoO4W4wHH50UNhOnjHmnOr3AmC0ZKrPIcZ6 uLUZgf/XDBUcT0+KCVYaHsOj+uFb/PfkVzhUNDaWgDN6m183VEbV6vGlguaHXvyhWB51 ZKj80+EnnCqqZUAlZ1kYeW1ksf0mCy+WFcY6ReXufTYgNwf135nowGviQqm5uKthzn3e Zq7mPTMRGnflC1LEwM0UOmeiaWa7d8WF88wFeAneV544uPJiPv+QYMIG9vWJTao0dqXy Q4+g== X-Gm-Message-State: APjAAAUnX2E4YqnV1Sct5mli+oJxLC+VWY+Gt36YIdHDIZfCK8Q8k87w /GLSaP+Lv+VVnpfoy6Jbo9UJSN6N X-Google-Smtp-Source: APXvYqyfrnyKdzFMkJ8IDVEeSSDxtZQkrR7Bn3TsXBGto2V/G6g46d2Mjhe7rRi4ukdvF82EhNKZmQ== X-Received: by 2002:a63:4e5f:: with SMTP id o31mr33740384pgl.49.1563278430537; Tue, 16 Jul 2019 05:00:30 -0700 (PDT) X-BeenThere: linux-amarula@amarulasolutions.com Received: by 2002:a17:902:6b81:: with SMTP id p1ls4223002plk.6.gmail; Tue, 16 Jul 2019 05:00:30 -0700 (PDT) X-Received: by 2002:a17:902:9688:: with SMTP id n8mr34057796plp.227.1563278430216; Tue, 16 Jul 2019 05:00:30 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1563278430; cv=none; d=google.com; s=arc-20160816; b=zyInX64ZTCUh6RzUjCNWUMLd1gMG8+varmCA/iqOndVcoEATGQhLUJEEXbHBOGvQ7o CClO6++kOHHd7jIyFf1KCNyjHuqIW3U1OTaFj1rYJVCuK5td0dRuqK4iL1ZMuzg0IVkN mYvp5WBvuuoEJlPvE0SuB+wB8Qeim3+N3HuRg5PBMFbbSg7pd/PBmke8U7LSrwST4NMF yYD4OFm4NohHQBrlxtC22jIK0HECeyb3ENVofalyp2wlD7lApIf3N7aD0/0HRLt/BBKJ i9U6IXUvV+/VjvCPsNJYqM4YJbDrR8jhzuv+RsGMBLvqaHZ6c4ET5oz3idYii2gq9Vsj rZgQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=b4BLaekI2K9GhOfNexihMzKGNJDUcPNIWa3ew4v23qw=; b=b31Rzhk3cOiycOun7csxOYK/8VVWtMlaYZJxwMJZCkI7CCdmZReb3UZiu6rPbkn+rk Ag9o8nbRK7ek9Ci4rVJ8al3+5ifqiCdhx3u4v9MbwlaULnsgfIGUHTC1xGORfuTt8++l 9jfH4uxFtPF8FCVrd+AkbdqEYrpiUnfgXKPi0hwtEpsYeSCvfa0oOAKE8ayvLw/MlK/B tF2oqLrGY0t36GgVl0eiHpsctTr7MJBTa3eQ2f+UcK3Dl3OX62Vr5EV+OxfBMrigFP0H lxsIkBA1K9mDmWWU7ZPFqGYlat2uxSxMSjKdPBIedVPKnd7/LrOxA5iD7gqj/5hawd2g BqkA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@amarulasolutions.com header.s=google header.b=K3lhGmSn; spf=pass (google.com: domain of jagan@amarulasolutions.com designates 209.85.220.65 as permitted sender) smtp.mailfrom=jagan@amarulasolutions.com Received: from mail-sor-f65.google.com (mail-sor-f65.google.com. [209.85.220.65]) by mx.google.com with SMTPS id r140sor2081432pgr.22.2019.07.16.05.00.30 for (Google Transport Security); Tue, 16 Jul 2019 05:00:30 -0700 (PDT) Received-SPF: pass (google.com: domain of jagan@amarulasolutions.com designates 209.85.220.65 as permitted sender) client-ip=209.85.220.65; X-Received: by 2002:a63:fb14:: with SMTP id o20mr22137271pgh.136.1563278429813; Tue, 16 Jul 2019 05:00:29 -0700 (PDT) Received: from localhost.localdomain ([49.206.201.107]) by smtp.gmail.com with ESMTPSA id z24sm36269566pfr.51.2019.07.16.05.00.26 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 16 Jul 2019 05:00:29 -0700 (PDT) From: Jagan Teki To: Simon Glass , Philipp Tomsich , Kever Yang , YouMin Chen , u-boot@lists.denx.de Cc: Manivannan Sadhasivam , gajjar04akash@gmail.com, linux-rockchip@lists.infradead.org, linux-amarula@amarulasolutions.com, Jagan Teki Subject: [PATCH v3 43/57] ram: rk3399: Add LPPDR4 mr detection Date: Tue, 16 Jul 2019 17:27:31 +0530 Message-Id: <20190716115745.12585-44-jagan@amarulasolutions.com> X-Mailer: git-send-email 2.18.0.321.gffc6fa0e3 In-Reply-To: <20190716115745.12585-1-jagan@amarulasolutions.com> References: <20190716115745.12585-1-jagan@amarulasolutions.com> MIME-Version: 1.0 X-Original-Sender: jagan@amarulasolutions.com X-Original-Authentication-Results: mx.google.com; dkim=pass header.i=@amarulasolutions.com header.s=google header.b=K3lhGmSn; spf=pass (google.com: domain of jagan@amarulasolutions.com designates 209.85.220.65 as permitted sender) smtp.mailfrom=jagan@amarulasolutions.com Content-Type: text/plain; charset="UTF-8" Precedence: list Mailing-list: list linux-amarula@amarulasolutions.com; contact linux-amarula+owners@amarulasolutions.com List-ID: X-Spam-Checked-In-Group: linux-amarula@amarulasolutions.com X-Google-Group-Id: 476853432473 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , Like data training in other sdram types, mr detection need to taken care for lpddr4 with looped rank and associated channel to make sure the proper configuration held. Once the mr detection successful for active and configured rank with channel number, the same can later reused during actual LPDDR4 initialization. So, add code to support for it. Signed-off-by: Jagan Teki Signed-off-by: YouMin Chen Reviewed-by: Kever Yang --- drivers/ram/rockchip/sdram_rk3399.c | 226 ++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+) diff --git a/drivers/ram/rockchip/sdram_rk3399.c b/drivers/ram/rockchip/sdram_rk3399.c index da01f08732..623685e3c5 100644 --- a/drivers/ram/rockchip/sdram_rk3399.c +++ b/drivers/ram/rockchip/sdram_rk3399.c @@ -1470,6 +1470,7 @@ static void dram_all_config(struct dram_info *dram, clrsetbits_le32(&dram->cru->glb_rst_con, 0x3, 0x3); } +#if !defined(CONFIG_RAM_RK3399_LPDDR4) static int default_data_training(struct dram_info *dram, u32 channel, u8 rank, struct rk3399_sdram_params *params) { @@ -1486,6 +1487,7 @@ static int default_data_training(struct dram_info *dram, u32 channel, u8 rank, return data_training(dram, channel, params, training_flag); } +#endif static int switch_to_phy_index1(struct dram_info *dram, const struct rk3399_sdram_params *params) @@ -1532,6 +1534,226 @@ static int switch_to_phy_index1(struct dram_info *dram, return 0; } +#if defined(CONFIG_RAM_RK3399_LPDDR4) +static u32 get_ddr_stride(struct rk3399_pmusgrf_regs *pmusgrf) +{ + return ((readl(&pmusgrf->soc_con4) >> 10) & 0x1F); +} + +static void set_ddr_stride(struct rk3399_pmusgrf_regs *pmusgrf, u32 stride) +{ + rk_clrsetreg(&pmusgrf->soc_con4, 0x1f << 10, stride << 10); +} + +static void set_cap_relate_config(const struct chan_info *chan, + struct rk3399_sdram_params *params, + unsigned int channel) +{ + u32 *denali_ctl = chan->pctl->denali_ctl; + u32 tmp; + struct rk3399_msch_timings *noc_timing; + + if (params->base.dramtype == LPDDR3) { + tmp = (8 << params->ch[channel].cap_info.bw) / + (8 << params->ch[channel].cap_info.dbw); + + /** + * memdata_ratio + * 1 -> 0, 2 -> 1, 4 -> 2 + */ + clrsetbits_le32(&denali_ctl[197], 0x7, + (tmp >> 1)); + clrsetbits_le32(&denali_ctl[198], 0x7 << 8, + (tmp >> 1) << 8); + } + + noc_timing = ¶ms->ch[channel].noc_timings; + + /* + * noc timing bw relate timing is 32 bit, and real bw is 16bit + * actually noc reg is setting at function dram_all_config + */ + if (params->ch[channel].cap_info.bw == 16 && + noc_timing->ddrmode.b.mwrsize == 2) { + if (noc_timing->ddrmode.b.burstsize) + noc_timing->ddrmode.b.burstsize -= 1; + noc_timing->ddrmode.b.mwrsize -= 1; + noc_timing->ddrtimingc0.b.burstpenalty *= 2; + noc_timing->ddrtimingc0.b.wrtomwr *= 2; + } +} + +static u32 calculate_ddrconfig(struct rk3399_sdram_params *params, u32 channel) +{ + unsigned int cs0_row = params->ch[channel].cap_info.cs0_row; + unsigned int col = params->ch[channel].cap_info.col; + unsigned int bw = params->ch[channel].cap_info.bw; + u16 ddr_cfg_2_rbc[] = { + /* + * [6] highest bit col + * [5:3] max row(14+n) + * [2] insertion row + * [1:0] col(9+n),col, data bus 32bit + * + * highbitcol, max_row, insertion_row, col + */ + ((0 << 6) | (2 << 3) | (0 << 2) | 0), /* 0 */ + ((0 << 6) | (2 << 3) | (0 << 2) | 1), /* 1 */ + ((0 << 6) | (1 << 3) | (0 << 2) | 2), /* 2 */ + ((0 << 6) | (0 << 3) | (0 << 2) | 3), /* 3 */ + ((0 << 6) | (2 << 3) | (1 << 2) | 1), /* 4 */ + ((0 << 6) | (1 << 3) | (1 << 2) | 2), /* 5 */ + ((1 << 6) | (0 << 3) | (0 << 2) | 2), /* 6 */ + ((1 << 6) | (1 << 3) | (0 << 2) | 2), /* 7 */ + }; + u32 i; + + col -= (bw == 2) ? 0 : 1; + col -= 9; + + for (i = 0; i < 4; i++) { + if ((col == (ddr_cfg_2_rbc[i] & 0x3)) && + (cs0_row <= (((ddr_cfg_2_rbc[i] >> 3) & 0x7) + 14))) + break; + } + + if (i >= 4) + i = -EINVAL; + + return i; +} + +/** + * read mr_num mode register + * rank = 1: cs0 + * rank = 2: cs1 + */ +static int read_mr(struct rk3399_ddr_pctl_regs *ddr_pctl_regs, u32 rank, + u32 mr_num, u32 *buf) +{ + s32 timeout = 100; + + writel(((1 << 16) | (((rank == 2) ? 1 : 0) << 8) | mr_num) << 8, + &ddr_pctl_regs->denali_ctl[118]); + + while (0 == (readl(&ddr_pctl_regs->denali_ctl[203]) & + ((1 << 21) | (1 << 12)))) { + udelay(1); + + if (timeout <= 0) { + printf("%s: pctl timeout!\n", __func__); + return -ETIMEDOUT; + } + + timeout--; + } + + if (!(readl(&ddr_pctl_regs->denali_ctl[203]) & (1 << 12))) { + *buf = readl(&ddr_pctl_regs->denali_ctl[119]) & 0xFF; + } else { + printf("%s: read mr failed with 0x%x status\n", __func__, + readl(&ddr_pctl_regs->denali_ctl[17]) & 0x3); + *buf = 0; + } + + setbits_le32(&ddr_pctl_regs->denali_ctl[205], (1 << 21) | (1 << 12)); + + return 0; +} + +static int lpddr4_mr_detect(struct dram_info *dram, u32 channel, u8 rank, + struct rk3399_sdram_params *params) +{ + u64 cs0_cap; + u32 stride; + u32 cs = 0, col = 0, bk = 0, bw = 0, row_3_4 = 0; + u32 cs0_row = 0, cs1_row = 0, ddrconfig = 0; + u32 mr5, mr12, mr14; + struct chan_info *chan = &dram->chan[channel]; + struct rk3399_ddr_pctl_regs *ddr_pctl_regs = chan->pctl; + void __iomem *addr = NULL; + int ret = 0; + u32 val; + + stride = get_ddr_stride(dram->pmusgrf); + + if (params->ch[channel].cap_info.col == 0) { + ret = -EPERM; + goto end; + } + + cs = params->ch[channel].cap_info.rank; + col = params->ch[channel].cap_info.col; + bk = params->ch[channel].cap_info.bk; + bw = params->ch[channel].cap_info.bw; + row_3_4 = params->ch[channel].cap_info.row_3_4; + cs0_row = params->ch[channel].cap_info.cs0_row; + cs1_row = params->ch[channel].cap_info.cs1_row; + ddrconfig = params->ch[channel].cap_info.ddrconfig; + + /* 2GB */ + params->ch[channel].cap_info.rank = 2; + params->ch[channel].cap_info.col = 10; + params->ch[channel].cap_info.bk = 3; + params->ch[channel].cap_info.bw = 2; + params->ch[channel].cap_info.row_3_4 = 0; + params->ch[channel].cap_info.cs0_row = 15; + params->ch[channel].cap_info.cs1_row = 15; + params->ch[channel].cap_info.ddrconfig = 1; + + set_memory_map(chan, channel, params); + params->ch[channel].cap_info.ddrconfig = + calculate_ddrconfig(params, channel); + set_ddrconfig(chan, params, channel, + params->ch[channel].cap_info.ddrconfig); + set_cap_relate_config(chan, params, channel); + + cs0_cap = (1 << (params->ch[channel].cap_info.bw + + params->ch[channel].cap_info.col + + params->ch[channel].cap_info.bk + + params->ch[channel].cap_info.cs0_row)); + + if (params->ch[channel].cap_info.row_3_4) + cs0_cap = cs0_cap * 3 / 4; + + if (channel == 0) + set_ddr_stride(dram->pmusgrf, 0x17); + else + set_ddr_stride(dram->pmusgrf, 0x18); + + /* read and write data to DRAM, avoid be optimized by compiler. */ + if (rank == 1) + addr = (void __iomem *)0x100; + else if (rank == 2) + addr = (void __iomem *)(cs0_cap + 0x100); + + val = readl(addr); + writel(val + 1, addr); + + read_mr(ddr_pctl_regs, rank, 5, &mr5); + read_mr(ddr_pctl_regs, rank, 12, &mr12); + read_mr(ddr_pctl_regs, rank, 14, &mr14); + + if (mr5 == 0 || mr12 != 0x4d || mr14 != 0x4d) { + ret = -EINVAL; + goto end; + } +end: + params->ch[channel].cap_info.rank = cs; + params->ch[channel].cap_info.col = col; + params->ch[channel].cap_info.bk = bk; + params->ch[channel].cap_info.bw = bw; + params->ch[channel].cap_info.row_3_4 = row_3_4; + params->ch[channel].cap_info.cs0_row = cs0_row; + params->ch[channel].cap_info.cs1_row = cs1_row; + params->ch[channel].cap_info.ddrconfig = ddrconfig; + + set_ddr_stride(dram->pmusgrf, stride); + + return ret; +} +#endif /* CONFIG_RAM_RK3399_LPDDR4 */ + static unsigned char calculate_stride(struct rk3399_sdram_params *params) { unsigned int stride = params->base.stride; @@ -1762,7 +1984,11 @@ static int conv_of_platdata(struct udevice *dev) #endif static const struct sdram_rk3399_ops rk3399_ops = { +#if !defined(CONFIG_RAM_RK3399_LPDDR4) .data_training = default_data_training, +#else + .data_training = lpddr4_mr_detect, +#endif }; static int rk3399_dmc_init(struct udevice *dev)