From patchwork Sun Aug 3 02:32:54 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Siarhei Siamashka X-Patchwork-Id: 375970 X-Patchwork-Delegate: hdegoede@redhat.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 07AD81400AA for ; Sun, 3 Aug 2014 12:35:51 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id EB5C94B5E4; Sun, 3 Aug 2014 04:35:30 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id tVq8RFBj-HxA; Sun, 3 Aug 2014 04:35:30 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id DE7694B617; Sun, 3 Aug 2014 04:34:17 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 256574B372 for ; Sun, 3 Aug 2014 04:34:16 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 65E3H9pRAN0s for ; Sun, 3 Aug 2014 04:34:12 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mail-lb0-f179.google.com (mail-lb0-f179.google.com [209.85.217.179]) by theia.denx.de (Postfix) with ESMTPS id 7F30B4B5FD for ; Sun, 3 Aug 2014 04:33:20 +0200 (CEST) Received: by mail-lb0-f179.google.com with SMTP id v6so4302588lbi.10 for ; Sat, 02 Aug 2014 19:33:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=0UHQvjKqrT/y+wp1uVzru3E7ComuUAgB8y/s1LIP0cA=; b=xH8P0GPisJUbZTj9sxWmQ2/BmnT7JLdZQT4jPX1WL5deTTXyB51dXfC4YfNjeo6ER5 JcLRX6Vy1bOlK8smPJVQEElvSCe52BFEmtdwXQlkoLWs3P5iHunl2XQUTejBZMS2GEOK c4JAdoTxvySTkmPkc8xF5U92rUjyZcbdP5s1snPUNoKb+hEjbfG+7Z93hoANakojC1HG kvIsKVxn7xqpgfSunGkYbGGqEMqNQxBdL9ufd4qCstaPAf8hWE7d6WARx8J/+m8HxUK0 PHW2gc5TAI0haD623V8zIENY9QUyRtd0UZuWzLbpd0GIlWwZucj93rCnoNKgDhMP6Odc h41w== X-Received: by 10.152.20.105 with SMTP id m9mr10961057lae.19.1407033200221; Sat, 02 Aug 2014 19:33:20 -0700 (PDT) Received: from localhost.localdomain ([212.16.98.80]) by mx.google.com with ESMTPSA id m1sm7381426laj.6.2014.08.02.19.33.18 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 02 Aug 2014 19:33:19 -0700 (PDT) From: Siarhei Siamashka To: u-boot@lists.denx.de Date: Sun, 3 Aug 2014 05:32:54 +0300 Message-Id: <1407033174-24603-17-git-send-email-siarhei.siamashka@gmail.com> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1407033174-24603-1-git-send-email-siarhei.siamashka@gmail.com> References: <1407033174-24603-1-git-send-email-siarhei.siamashka@gmail.com> Cc: Ian Campbell , linux-sunxi@googlegroups.com Subject: [U-Boot] [PATCH v2 16/16] sunxi: dram: Autodetect DDR3 bus width and density X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de In the case if the 'dram_para' struct does not specify the exact bus width or chip density, just use a trial and error method to find a usable configuration. Because all the major bugs in the DRAM initialization sequence are now hopefully fixed, it should be safe to re-initialize the DRAM controller multiple times until we get it configured right. The original Allwinner's boot0 bootloader also used a similar autodetection trick. The DDR3 spec contains the package pinout and addressing table for different possible chip densities. It appears to be impossible to distinguish between a single chip with 16 I/O data lines and a pair of chips with 8 I/O data lines in the case if they provide the same storage capacity. Because a single 16-bit chip has a higher density than a pair of equivalent 8-bit chips, it has stricter refresh timings. So in the case of doubt, we assume that 16-bit chips are used. Additionally, only Allwinner A20 has all A0-A15 address lines and can support densities up to 8192. The older Allwinner A10 and Allwinner A13 can only support densities up to 4096. We deliberately leave out DDR2, dual-rank configurations and the special case of a 8-bit chip with density 8192. None of these configurations seem to have been ever used in real devices. And no new devices are likely to use these exotic configurations (because only up to 2GB of RAM can be populated in any case). This DRAM autodetection feature potentially allows to have a single low performance fail-safe DDR3 initialiazation for a universal single bootloader binary, which can be compatible with all Allwinner A10/A13/A20 based devices (if the ifdefs are replaced with a runtime SoC type detection). Signed-off-by: Siarhei Siamashka Acked-by: Ian Campbell --- Changes for v2: - break lines in the commit message in order not to exceed 72 characters line limit - no other changes arch/arm/cpu/armv7/sunxi/dram.c | 52 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/arch/arm/cpu/armv7/sunxi/dram.c b/arch/arm/cpu/armv7/sunxi/dram.c index 2ad685b..584f742 100644 --- a/arch/arm/cpu/armv7/sunxi/dram.c +++ b/arch/arm/cpu/armv7/sunxi/dram.c @@ -572,17 +572,13 @@ static void mctl_set_impedance(u32 zq, u32 odt_en) writel(DRAM_IOCR_ODT_EN(odt_en), &dram->iocr); } -unsigned long dramc_init(struct dram_para *para) +static unsigned long dramc_init_helper(struct dram_para *para) { struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE; u32 reg_val; u32 density; int ret_val; - /* check input dram parameter structure */ - if (!para) - return 0; - /* * only single rank DDR3 is supported by this code even though the * hardware can theoretically support DDR2 and up to two ranks @@ -706,3 +702,49 @@ unsigned long dramc_init(struct dram_para *para) return get_ram_size((long *)PHYS_SDRAM_0, PHYS_SDRAM_0_SIZE); } + +unsigned long dramc_init(struct dram_para *para) +{ + unsigned long dram_size, actual_density; + + /* If the dram configuration is not provided, use a default */ + if (!para) + return 0; + + /* if everything is known, then autodetection is not necessary */ + if (para->io_width && para->bus_width && para->density) + return dramc_init_helper(para); + + /* try to autodetect the DRAM bus width and density */ + para->io_width = 16; + para->bus_width = 32; +#if defined(CONFIG_SUN4I) || defined(CONFIG_SUN5I) + /* only A0-A14 address lines on A10/A13, limiting max density to 4096 */ + para->density = 4096; +#else + /* all A0-A15 address lines on A20, which allow density 8192 */ + para->density = 8192; +#endif + + dram_size = dramc_init_helper(para); + if (!dram_size) { + /* if 32-bit bus width failed, try 16-bit bus width instead */ + para->bus_width = 16; + dram_size = dramc_init_helper(para); + if (!dram_size) { + /* if 16-bit bus width also failed, then bail out */ + return dram_size; + } + } + + /* check if we need to adjust the density */ + actual_density = (dram_size >> 17) * para->io_width / para->bus_width; + + if (actual_density != para->density) { + /* update the density and re-initialize DRAM again */ + para->density = actual_density; + dram_size = dramc_init_helper(para); + } + + return dram_size; +}