From patchwork Mon Jun 17 07:32:35 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jagan Teki X-Patchwork-Id: 653 Return-Path: X-Original-To: linux-amarula@patchwork.amarulasolutions.com Delivered-To: linux-amarula@patchwork.amarulasolutions.com Received: from mail-pg1-f198.google.com (mail-pg1-f198.google.com [209.85.215.198]) by ganimede.amarulasolutions.com (Postfix) with ESMTPS id 56ADC3F353 for ; Mon, 17 Jun 2019 09:40:55 +0200 (CEST) Received: by mail-pg1-f198.google.com with SMTP id p7sf1398193pgr.10 for ; Mon, 17 Jun 2019 00:40:55 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1560757254; cv=pass; d=google.com; s=arc-20160816; b=XHNvNlfd9+phozRs7H753SJfeLHw91Mdxrk05TeYkA+phgTZwI2ypodB5OkLB6ECsA esjnxS1OZPp8q2Y6aTp5DYZkvhWjCLA7SU98yHDQf2hn7mTgJSsGk6X7DJmfV0m8rWkt sjNI8eNtjJIOLiFjiMeDzzuvyc5+1tTN07frjC1+lfx/NsJeA9j0SZ/piEROWyZFnXZ8 CgaQ6tem6a7TmPDIZ5mAU89UAcECV5oj7KmYg8BtoizIKLSUACsIhtE9d2NJK9aG6WSU InZaYCNe/n2y68Y5yit+bdVxKwSMVVZUvfzdVrs9piXNm+yuSPv6RaMiPXaCYp7i1Sub XHDA== 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=dfBnq7N+Olajh0k4GM++rOAPyIT8SucSIZxtJ4FAEpo=; b=bLvkoj8XAE49DRh7k0kfg+JcM2Elt2yJg/2Zt7sJez+um6oj5FqqniSFP19cWW76cV 0sFx24f/Nl0TpCVPWwtONxRgX6cOnF2Ia98y3lVIdvN02m5IFJwdR3NFsbuv7xOdJFuG b8fEK/JNv8/CWkxVr+iNwtsdquWRuEy3RW7VX50uyW4XQCog8lz3XyEDmj1dEkkL7tKE McmCTZbCY3NtWKPoXngE8IGBTL9Laf6YLs457l0RQbThEtwD7jE6lvVMM7x/+qrqf4+6 sDF/wORh39mbiXmuGUv2Mx5NF0woJdcRvb/vtRr31WZyF2ai26sDZahYEhkGXzAF6TBH 4XTw== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@amarulasolutions.com header.s=google header.b=F9TD5K09; 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=dfBnq7N+Olajh0k4GM++rOAPyIT8SucSIZxtJ4FAEpo=; b=NHcKCoe8jPhbBn0Lm1qZpmDx/u+hijx2ked6gEvHFstoPvWp8/BYYFLJ0lnoubRR4X jMYYx83K+tH2VLgRZqzKMoj/XHaBYd9oJYCblEban2cz5Jpon+SziZEhuDxNcUXprXyH QctsIZqeviO+1av771olOWi3E3UPVIMrxBWsk= 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=dfBnq7N+Olajh0k4GM++rOAPyIT8SucSIZxtJ4FAEpo=; b=HdgwK1wryCca4aERII9mtnlZ6Wo52bo8pqdXq1hRJV87TcU+/HOpbaDz+HJIKemsIm SGID0kzlXWSR/9vnHjD2zUJOujDIg4EcJcQP54dKY9G672NeiaiPx1sQ1ET6cF4IdKBk cLfOvZ82K39m8Ifca9lrmly1bILQxUWKKLRRnMpj9W4BgTfMrghC7jQTDKXuViFFf7Wk JxHB0S4uY2rrnZjYmR6BECuZSU6/v003D16Viamqt9rhL23URBso3VwJxt72PDor5WPJ RB5uKHyizNq3072tpYsJFpdBXPNAE8ZxCk/fMGj5Sqvie1fajGfBZpyR7A1JY2I7hmsA wEVQ== X-Gm-Message-State: APjAAAXM2rDK8Ku1yMR67GxN2UttI9eSagHztLQgPOK/snO9Wfr9jSym zU6sI8BISeJuCMOkvbJpcj4kS57V X-Google-Smtp-Source: APXvYqxSSjFfYF0yfZCYy0ReFGS01oDKpNMN+WtJbmL5K5rmTTtu/47U4xyqoPXL9uteeX9rFKX/pQ== X-Received: by 2002:a65:44c8:: with SMTP id g8mr47659488pgs.443.1560757254022; Mon, 17 Jun 2019 00:40:54 -0700 (PDT) X-BeenThere: linux-amarula@amarulasolutions.com Received: by 2002:a63:d50a:: with SMTP id c10ls2174717pgg.10.gmail; Mon, 17 Jun 2019 00:40:53 -0700 (PDT) X-Received: by 2002:aa7:9317:: with SMTP id 23mr24050193pfj.79.1560757253670; Mon, 17 Jun 2019 00:40:53 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1560757253; cv=none; d=google.com; s=arc-20160816; b=vWtnkEeEcsN4EwLpGPF8x/lUW48MYW9S8Jupa0lvo02Qr6tcQiOFRAkwLBb2QVlTF8 XZ1rIQ896asNLzcyBmFnS7TotgYYRXtBiC4yopvt/8HFTVGRdGbTZWl2SsU6L1LdBLIq /EOMgH6+6rrAgtBlaKspdQggy3eqFuO6+6p5tirIMKxCcn6w06ROyoMDCZXC0gO0SS4z +3+UjfcvOyMwrWDlT3IG5xQOzFNgk5uAtd92RnYP0AFrYr/6J/6MfxkQNJjFgKh518Yg LPHrlVlufToUi3hA5Vc1C7l7EHvqjweO/2fR5QsZtAf+FTpg/7IUJckofA+Vqrdwn5Rh /D1Q== 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=E+Jhc/d0ckFOoLtINRqwNEbOP94PVVM2QgBM4bNeHzY=; b=fginJ/aYvDyY5n6IrE6I7j2eChnWVPHtL+x9/eFhroGNnslWb5NbI3KmhiCiMzR8Mx /2/3HamPX4LdIQ5ItL1nL2UUPfGY5cv+fvV1RwEjbKVIcdeh4Z6QZyALyfeyM/NPiP7v IlEhNpbeK5qIW9jHzs50oaJ7S4n0no1ges//rfcJdlmAuDTbgNFIhv4LvPkbC74pcPPH 75K1f/FTKqy0bA2+qoeKKi6fYdoTzT3KDzJ8/nG8f1+G10O74rV811jPV2MwlDU72NAh GZ4s+lBtHpMxinpRsZOAGiH0DxrBllThF23lTs+HjsmvjoKNc11Bmc+hA87JVW5k9g9z F2Vw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@amarulasolutions.com header.s=google header.b=F9TD5K09; 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 v13sor10094150pgs.55.2019.06.17.00.40.53 for (Google Transport Security); Mon, 17 Jun 2019 00:40:53 -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:6111:: with SMTP id v17mr47756268pgb.206.1560757253194; Mon, 17 Jun 2019 00:40:53 -0700 (PDT) Received: from localhost.localdomain ([49.206.203.245]) by smtp.gmail.com with ESMTPSA id m41sm15205998pje.18.2019.06.17.00.40.50 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 17 Jun 2019 00:40:52 -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 v2 82/99] ram: rk3399: Add LPPDR4 mr detection Date: Mon, 17 Jun 2019 13:02:35 +0530 Message-Id: <20190617073252.27810-83-jagan@amarulasolutions.com> X-Mailer: git-send-email 2.18.0.321.gffc6fa0e3 In-Reply-To: <20190617073252.27810-1-jagan@amarulasolutions.com> References: <20190617073252.27810-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=F9TD5K09; 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 --- 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 e2b311193d..cdae6b9e67 100644 --- a/drivers/ram/rockchip/sdram_rk3399.c +++ b/drivers/ram/rockchip/sdram_rk3399.c @@ -1471,6 +1471,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) { @@ -1487,6 +1488,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) @@ -1533,6 +1535,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; @@ -1763,7 +1985,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)