From patchwork Tue Jun 11 14:51:21 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jagan Teki X-Patchwork-Id: 529 Return-Path: X-Original-To: linux-amarula@patchwork.amarulasolutions.com Delivered-To: linux-amarula@patchwork.amarulasolutions.com Received: from mail-pf1-f199.google.com (mail-pf1-f199.google.com [209.85.210.199]) by ganimede.amarulasolutions.com (Postfix) with ESMTPS id AC1AD3F08A for ; Tue, 11 Jun 2019 16:57:01 +0200 (CEST) Received: by mail-pf1-f199.google.com with SMTP id d125sf9788021pfd.3 for ; Tue, 11 Jun 2019 07:57:01 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1560265020; cv=pass; d=google.com; s=arc-20160816; b=RU9ESS3Y1BJUL7MTgPIwgnFW/DzSc4ceGNp3ZNaqTR+dI5kRZDEs4hF5Q3XE4ho2Dg f2cR77YNB8ZvZlw/4/fGb3hVeP6fLrBP9esEAZAXZH78ksqdzBcATpFjx1wKCsUIpSL1 jrlBRoSMbtYCs1yEtIoe1CW9R6aq4VHOCoBZJOlf7xRD3WvBXHbjJFQFBm+HR1vXQYPS rqHdvl4qU8nwhiUQ+BeVfEouU34+GDpLmfe3r9U+qdrqtlAn8u4V0jzpjmU23LneBaIo cHJH3ROrRakNqqVB5t09Z5GkdCS+BphEwk4GW3vCZhLDxdbzzt5KYt8HmnSOBVDxE3Fn iwig== 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=YCbiN1G6MHlkBTF8Nhk+ZdWaqbNxCbYqTcCvB8iEiGk=; b=b2sFJ5J80XRGv8cmJawH/hSMXkhcSDdgATM4PqujT0+DPiAVfVuM6UQ0V8EJLmp07n vdhlmwV8pLgBzH+TIUO+a4ejiu+qHfkbuKgJiTICL8B3W+c8aOg12m6Nxt1ml1Rh26uJ OM3oaQIMR1o3M224UzEEiz1CAZtNG2dS+N32LEbOsUf2Qdjt06WdylYh/KgAe042+ZoD LJ3vX8R0BfpJ/DyiiIMgtDDY0F1HFCgG0ZG5+W+/Eb3Uk1I9I+ByfWmQvX8OsecJX+5U 24TCE9W5nhUefsTkh+fFd6KlkCfDhoMO4Lya3bopcHZsROoU2I3HExcSzXN5WdCb8gdN c6hg== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@amarulasolutions.com header.s=google header.b=kVthj+Xr; 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=YCbiN1G6MHlkBTF8Nhk+ZdWaqbNxCbYqTcCvB8iEiGk=; b=al9TtXJV+LDr8BgMwndmAFkXJQ5FL/td0BqxpMhCt34iV8gbAZV566KXBMjznlqERf +lZtf1NL2TILLd3AgzjL+siySW+h9iGmVbV8TUewYxZSWO//zY6T7Kp75Mk9zoZE6SiU 4PZVwY6msX1IzUCKrphPAF3n8+2rFbB8XOwOo= 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=YCbiN1G6MHlkBTF8Nhk+ZdWaqbNxCbYqTcCvB8iEiGk=; b=CLXWjCuhkWu3OSCBg3ull6M3vuLcHiSEK+TH+pvHUYzqZjWjM4NR1w31ogJc28p/fN SSgRkfkNkrCNFzKZr8Un8IzdoluEr4U1Gr8k+OEEb2jTiHh2iAPAyR80OL8ufWNXpLEU RUZKZ51VYsOEwqdjfe8sHB6RN/oEJK2h48NlkqXJhpYRej5M7Q5LyckgWFsmHf7Z9AvJ lXH5JZIR0F0H8LG+1JTOinDPORri1JW9dljt9cNZmgbXpHM9UFvLVE2cnezs9zZFVIdj RMK5gULfE747QRiuXDjBwDIgtFrShNV2K1lD91YMI42RZRDBopQWXxYSVjfWwZQn7nuB NpCw== X-Gm-Message-State: APjAAAXNkylP2Qdn2yezGPCCCI4jPJyUQFrhs4WUMIxzbjwsXzzT1Qhl +0a3oFkQ3ggutgGziaODZ4y8rZku X-Google-Smtp-Source: APXvYqzeQoxtF0rINotuknoDq9ofIz7yjWnlQZYEEoh3mUnL9nXezdIi1w0MDWBjYUOwZzwnO5D2UA== X-Received: by 2002:aa7:8083:: with SMTP id v3mr1862770pff.69.1560265020415; Tue, 11 Jun 2019 07:57:00 -0700 (PDT) X-BeenThere: linux-amarula@amarulasolutions.com Received: by 2002:a63:1463:: with SMTP id 35ls23657pgu.5.gmail; Tue, 11 Jun 2019 07:57:00 -0700 (PDT) X-Received: by 2002:a63:5024:: with SMTP id e36mr21449816pgb.220.1560265019728; Tue, 11 Jun 2019 07:56:59 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1560265019; cv=none; d=google.com; s=arc-20160816; b=v13PQ++WJyxwz3B6HPP5VzlRhb2zrtpV7uwin+bofh9iH5rEZWW14HELN4awSKR6f0 aYak7ZNrcEGEddV/OykVLAfnhFrHkZofOS8c1QZXlrqtixvKaZYq5g6TtA3bxRvkxPMe xizmlEgCCb0wjZnGQoGI+N77GEuZxw8Z9031SekmWR3CQ/KM6IMJWzuJ4gx6K9hvTIrf xPNjhL9i7r/BkBjw+UIizQmCfsn7AOFgat8TsuzPDfPgUvXT19qvLMYtB7NLFLa6RW3J eIzxo2Akq9IoDz/rD8qkDlsUh9YMuBwKKOSmCPZ+9xGLWHpnIPdT2C1rtlwQuvQREJDI LZaQ== 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=mGAVbQ0/GKtxUT4Ixc2BHlNx/P364Q0MbJKj7oZiPw0=; b=OvWXe9cuGWADdFoG2iCu7hCbeKoEvNJS3qLwciW4/bulzDJ8yZprKSAeS5uwRkiDZ6 K8P4BqdK79CTN2/Wb2TE10jLp/iVBFbGeJfDE9WP7Ccw9sehVlaFvK7eQYeF//ZMSkAd gHegOnaQXp1UxpAKLd7lmXajkzIFgI5s6d/zfNZ0WBBoVPhg6pAQw5O2p76vJ0WoZnxC 0EpjwLBtWDA10uAehrs87n/AC5qilRiECa6wyM3gJzp7rH9stkxX1zZ+odIfciZl1F0H +TLFYI5oO+/+QVwUrAb9WS1Eb4a+CwCn4GsvzBO+z3ufzhMmUPKMEJCmGkwc0VoIoxS2 gHgA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@amarulasolutions.com header.s=google header.b=kVthj+Xr; 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 123sor7597159pfu.0.2019.06.11.07.56.59 for (Google Transport Security); Tue, 11 Jun 2019 07:56:59 -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:a62:36c1:: with SMTP id d184mr82811975pfa.49.1560265019396; Tue, 11 Jun 2019 07:56:59 -0700 (PDT) Received: from localhost.localdomain ([115.97.180.18]) by smtp.gmail.com with ESMTPSA id e9sm16206208pfn.154.2019.06.11.07.56.55 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 11 Jun 2019 07:56:58 -0700 (PDT) From: Jagan Teki To: Simon Glass , Philipp Tomsich , Kever Yang , YouMin Chen , u-boot@lists.denx.de Cc: gajjar04akash@gmail.com, linux-rockchip@lists.infradead.org, linux-amarula@amarulasolutions.com, Jagan Teki Subject: [PATCH 78/92] ram: rk3399: Add LPPDR4 mr detection Date: Tue, 11 Jun 2019 20:21:21 +0530 Message-Id: <20190611145135.21399-79-jagan@amarulasolutions.com> X-Mailer: git-send-email 2.18.0.321.gffc6fa0e3 In-Reply-To: <20190611145135.21399-1-jagan@amarulasolutions.com> References: <20190611145135.21399-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=kVthj+Xr; 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 | 254 ++++++++++++++++++++++++++-- 1 file changed, 243 insertions(+), 11 deletions(-) diff --git a/drivers/ram/rockchip/sdram_rk3399.c b/drivers/ram/rockchip/sdram_rk3399.c index 89348cf296..5a0872c23f 100644 --- a/drivers/ram/rockchip/sdram_rk3399.c +++ b/drivers/ram/rockchip/sdram_rk3399.c @@ -218,6 +218,16 @@ static void *get_ddrc0_con(struct dram_info *dram, u8 channel) return (channel == 0) ? &dram->grf->ddrc0_con0 : &dram->grf->ddrc0_con1; } +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 copy_to_reg(u32 *dest, const u32 *src, u32 n) { int i; @@ -1593,6 +1603,215 @@ static unsigned char calculate_stride(struct rk3399_sdram_params *sdram_params) return stride; } +static void set_cap_relate_config(const struct chan_info *chan, + struct rk3399_sdram_params *sdram_params, + unsigned int channel) +{ + u32 *denali_ctl = chan->pctl->denali_ctl; + u32 tmp; + struct rk3399_msch_timings *noc_timing; + + if (sdram_params->base.dramtype == LPDDR3) { + tmp = (8 << sdram_params->ch[channel].cap_info.bw) / + (8 << sdram_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 = &sdram_params->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 (sdram_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 *sdram_params, + u32 channel) +{ + unsigned int cs0_row = sdram_params->ch[channel].cap_info.cs0_row; + unsigned int col = sdram_params->ch[channel].cap_info.col; + unsigned int bw = sdram_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, u32 rank, + struct rk3399_sdram_params *sdram_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 (sdram_params->ch[channel].cap_info.col == 0) { + ret = -EPERM; + goto end; + } + + cs = sdram_params->ch[channel].cap_info.rank; + col = sdram_params->ch[channel].cap_info.col; + bk = sdram_params->ch[channel].cap_info.bk; + bw = sdram_params->ch[channel].cap_info.bw; + row_3_4 = sdram_params->ch[channel].cap_info.row_3_4; + cs0_row = sdram_params->ch[channel].cap_info.cs0_row; + cs1_row = sdram_params->ch[channel].cap_info.cs1_row; + ddrconfig = sdram_params->ch[channel].cap_info.ddrconfig; + + /* 2GB */ + sdram_params->ch[channel].cap_info.rank = 2; + sdram_params->ch[channel].cap_info.col = 10; + sdram_params->ch[channel].cap_info.bk = 3; + sdram_params->ch[channel].cap_info.bw = 2; + sdram_params->ch[channel].cap_info.row_3_4 = 0; + sdram_params->ch[channel].cap_info.cs0_row = 15; + sdram_params->ch[channel].cap_info.cs1_row = 15; + sdram_params->ch[channel].cap_info.ddrconfig = 1; + + set_memory_map(chan, channel, sdram_params); + sdram_params->ch[channel].cap_info.ddrconfig = + calculate_ddrconfig(sdram_params, channel); + set_ddrconfig(chan, sdram_params, channel, + sdram_params->ch[channel].cap_info.ddrconfig); + set_cap_relate_config(chan, sdram_params, channel); + + cs0_cap = (1 << (sdram_params->ch[channel].cap_info.bw + + sdram_params->ch[channel].cap_info.col + + sdram_params->ch[channel].cap_info.bk + + sdram_params->ch[channel].cap_info.cs0_row)); + + if (sdram_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: + sdram_params->ch[channel].cap_info.rank = cs; + sdram_params->ch[channel].cap_info.col = col; + sdram_params->ch[channel].cap_info.bk = bk; + sdram_params->ch[channel].cap_info.bw = bw; + sdram_params->ch[channel].cap_info.row_3_4 = row_3_4; + sdram_params->ch[channel].cap_info.cs0_row = cs0_row; + sdram_params->ch[channel].cap_info.cs1_row = cs1_row; + sdram_params->ch[channel].cap_info.ddrconfig = ddrconfig; + + set_ddr_stride(dram->pmusgrf, stride); + + return ret; +} + static void clear_channel_params(struct rk3399_sdram_params *params, u8 channel) { params->ch[channel].cap_info.rank = 0; @@ -1665,17 +1884,30 @@ static int sdram_init(struct dram_info *dram, sdram_params->ch[ch].cap_info.rank = rank; - /* - * LPDDR3 CA training msut be trigger before - * other training. - * DDR3 is not have CA training. - */ - if (sdram_params->base.dramtype == LPDDR3) - training_flag |= PI_CA_TRAINING; - - if (!(data_training(&dram->chan[ch], ch, - sdram_params, training_flag))) - break; + if (sdram_params->base.dramtype == LPDDR4) { + if (!lpddr4_mr_detect(dram, ch, rank, + sdram_params)) { + debug("%s: lpddr4 mr detected for rank %d, ch %d\n", + __func__, rank, ch); + break; + } + } else { + /* + * LPDDR3 CA training msut be trigger before + * other training. + * DDR3 is not have CA training. + */ + if (sdram_params->base.dramtype == LPDDR3) + training_flag |= PI_CA_TRAINING; + + if (!(data_training(&dram->chan[ch], ch, + sdram_params, + training_flag))) { + debug("%s: data trained for rank %d, ch %d\n", + __func__, rank, ch); + break; + } + } } /* Computed rank with associated channel number */ sdram_params->ch[ch].cap_info.rank = rank;