From: Heiko Stuebner <heiko@sntech.de>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v3 13/16] rockchip: rk3188: Add sdram driver
Date: Fri, 17 Feb 2017 21:39:51 +0100 [thread overview]
Message-ID: <3647173.obZyHJeQ1U@phil> (raw)
In-Reply-To: <CAPnjgZ3NuzM_dCa5P_y7immBwd-V5qbiLgajekhc_YDQA0Um9A@mail.gmail.com>
Hi Simon,
Am Montag, 6. Februar 2017, 07:35:23 CET schrieb Simon Glass:
> On 3 February 2017 at 08:09, Heiko Stuebner <heiko@sntech.de> wrote:
> > The sdram controller blocks are very similar to the rk3288 in utilizing
> > memory scheduler, Designware uPCTL and Designware PUBL blocks, only
> > limited to one bank instead of two.
> >
> > There are some minimal differences when setting up the ram, so it gets
> > a separate driver for the rk3188 but reuses the driver structs, as there
> > is no need to define the same again.
> >
> > More optimization can happen when the modelling of the controller parts
> > in the dts actually follow the hardware layout hopefully at some point
> > in the future.
> >
> > Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> > ---
> >
> > arch/arm/include/asm/arch-rockchip/ddr_rk3188.h | 22 +
> > arch/arm/mach-rockchip/rk3188/Makefile | 1 +
> > arch/arm/mach-rockchip/rk3188/sdram_rk3188.c | 985
> > ++++++++++++++++++++++++ 3 files changed, 1008 insertions(+)
> > create mode 100644 arch/arm/include/asm/arch-rockchip/ddr_rk3188.h
> > create mode 100644 arch/arm/mach-rockchip/rk3188/sdram_rk3188.c
>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> Nits below.
>
> > diff --git a/arch/arm/include/asm/arch-rockchip/ddr_rk3188.h
> > b/arch/arm/include/asm/arch-rockchip/ddr_rk3188.h new file mode 100644
> > index 0000000000..993c58d1a8
> > --- /dev/null
> > +++ b/arch/arm/include/asm/arch-rockchip/ddr_rk3188.h
> > @@ -0,0 +1,22 @@
> > +/*
> > + * (C) Copyright 2015 Google, Inc
> > + *
> > + * SPDX-License-Identifier: GPL-2.0
> > + */
> > +
> > +#ifndef _ASM_ARCH_DDR_RK3188_H
> > +#define _ASM_ARCH_DDR_RK3188_H
> > +
> > +#include <asm/arch/ddr_rk3288.h>
> > +
> > +struct rk3188_msch {
> > + u32 coreid;
> > + u32 revisionid;
> > + u32 ddrconf;
> > + u32 ddrtiming;
> > + u32 ddrmode;
> > + u32 readlatency;
>
> Can you comment this struct? What is it for?
Added a comment that this the memory scheduler register map, but that is all I
can say for it, as it is sparsely documented in the chip manuals.
> > +#ifdef CONFIG_SPL_BUILD
> > +static void copy_to_reg(u32 *dest, const u32 *src, u32 n)
>
> Seems like this should go in a common file as there are several users
> - rk_copy_to_reg() ?
Right now we don't have a common file with shared code and as that function is
specific to the SPL build I'm not sure if it wouldn't cause issues if we have a
big bunch of common code that gets included in all SPLs.
Looking at my compilation result, it looks like the compiler inlined the
function anyway, so maybe just define it as inline in the hardware.h ?
>
> > +{
> > + int i;
> > +
> > + for (i = 0; i < n / sizeof(u32); i++) {
> > + writel(*src, dest);
> > + src++;
> > + dest++;
> > + }
> > +}
[...]
> > +static void phy_dll_bypass_set(struct rk3288_ddr_publ *publ,
> > + u32 freq)
> > +{
> > + int i;
>
> blank line here
>
> Do you have a comment for this logic, and why it is how it is?
Not really ... the memory controllers of the rk3066,rk3188 are very much
similar to the rk3288, so this simply mirrors your own sdram code from rk3288
;-) .
Speaking of duplicate code, you might already realize that this sdram driver
is very much similar to the rk3288.
My current plan is to submit the rk3188 separately at first and after
everything lands try to make the common code shared.
rk3066, rk3188 and rk3288 all use a dw-upctl + dw-publ + phy, with some
minimal differences, while the rk3036 uses a dw-upctl with a different phy
block, so it might get a bit tricky on where to share and how to name stuff.
Also another developer seems to be working on rk3066 uboot support already, so
it might be interesting to see if this will also require additional
adaptations.
> > + if (freq <= 250000000) {
> > + if (freq <= 150000000)
> > + clrbits_le32(&publ->dllgcr, SBIAS_BYPASS);
> > + else
> > + setbits_le32(&publ->dllgcr, SBIAS_BYPASS);
> > + setbits_le32(&publ->acdllcr, ACDLLCR_DLLDIS);
> > + for (i = 0; i < 4; i++)
> > + setbits_le32(&publ->datx8[i].dxdllcr,
> > + DXDLLCR_DLLDIS);
> > +
> > + setbits_le32(&publ->pir, PIR_DLLBYP);
> > + } else {
> > + clrbits_le32(&publ->dllgcr, SBIAS_BYPASS);
> > + clrbits_le32(&publ->acdllcr, ACDLLCR_DLLDIS);
> > + for (i = 0; i < 4; i++) {
> > + clrbits_le32(&publ->datx8[i].dxdllcr,
> > + DXDLLCR_DLLDIS);
> > + }
> > +
> > + clrbits_le32(&publ->pir, PIR_DLLBYP);
> > + }
> > +}
[...]
> > +static void ddr_set_ddr3_mode(struct rk3188_grf *grf, uint channel,
> > + bool ddr3_mode)
> > +{
> > + uint mask, val;
> > +
> > + mask = 1 << MSCH4_MAINDDR3_SHIFT;
> > + val = ddr3_mode << MSCH4_MAINDDR3_SHIFT;
> > + rk_clrsetreg(&grf->soc_con2, mask, val);
> > +}
> > +
> > +#define RANK_2_ROW15_EN 1
>
> Can this go at the top of the file?
actually already contained in the grf header, so can be simply used from there
> > +static void ddr_rank_2_row15en(struct rk3188_grf *grf, bool enable)
> > +{
> > + uint mask, val;
> > +
> > + mask = 1 << RANK_2_ROW15_EN;
> > + val = enable << RANK_2_ROW15_EN;
> > + rk_clrsetreg(&grf->soc_con2, mask, val);
> > +}
> > +static int data_training(const struct chan_info *chan, u32 channel,
> > + struct rk3188_sdram_params *sdram_params)
>
> Function comment? What does it return? channel could just be int, right?
I'm not particular insighted on what this code actually does, except what the
function name implies ;-) ... but I did swap the channel to int.
>
> > +{
> > + unsigned int j;
> > + int ret = 0;
> > + u32 rank;
> > + int i;
> > + u32 step[2] = { PIR_QSTRN, PIR_RVTRN };
> > + struct rk3288_ddr_publ *publ = chan->publ;
> > + struct rk3288_ddr_pctl *pctl = chan->pctl;
> > +
> > + /* disable auto refresh */
> > + writel(0, &pctl->trefi);
> > +
> > + if (sdram_params->base.dramtype != LPDDR3)
> > + setbits_le32(&publ->pgcr, 1 << PGCR_DQSCFG_SHIFT);
> > + rank = sdram_params->ch[channel].rank | 1;
> > + for (j = 0; j < ARRAY_SIZE(step); j++) {
> > + /*
> > + * trigger QSTRN and RVTRN
> > + * clear DTDONE status
> > + */
> > + setbits_le32(&publ->pir, PIR_CLRSR);
> > +
> > + /* trigger DTT */
> > + setbits_le32(&publ->pir,
> > + PIR_INIT | step[j] | PIR_LOCKBYP |
> > PIR_ZCALBYP | + PIR_CLRSR);
> > + udelay(1);
> > + /* wait echo byte DTDONE */
> > + while ((readl(&publ->datx8[0].dxgsr[0]) & rank)
> > + != rank)
> > + ;
> > + while ((readl(&publ->datx8[1].dxgsr[0]) & rank)
> > + != rank)
> > + ;
> > + if (!(readl(&pctl->ppcfg) & 1)) {
> > + while ((readl(&publ->datx8[2].dxgsr[0])
> > + & rank) != rank)
> > + ;
> > + while ((readl(&publ->datx8[3].dxgsr[0])
> > + & rank) != rank)
> > + ;
> > + }
> > + if (readl(&publ->pgsr) &
> > + (PGSR_DTERR | PGSR_RVERR | PGSR_RVEIRR)) {
> > + ret = -1;
> > + break;
> > + }
> > + }
> > + /* send some auto refresh to complement the lost while DTT */
> > + for (i = 0; i < (rank > 1 ? 8 : 4); i++)
> > + send_command(pctl, rank, REF_CMD, 0);
> > +
> > + if (sdram_params->base.dramtype != LPDDR3)
> > + clrbits_le32(&publ->pgcr, 1 << PGCR_DQSCFG_SHIFT);
> > +
> > + /* resume auto refresh */
> > + writel(sdram_params->pctl_timing.trefi, &pctl->trefi);
> > +
> > + return ret;
> > +}
> > +
> > +const int ddrconf_table[] = {
> > + /*
> > + * [5:4] row(13+n)
> > + * [1:0] col(9+n), assume bw=2
> > + * row col,bw */
> > + 0,
> > + ((2 << 4) | 1),
> > + ((1 << 4) | 1),
> > + ((0 << 4) | 1),
> > + ((2 << 4) | 2),
> > + ((1 << 4) | 2),
> > + ((0 << 4) | 2),
> > + ((1 << 4) | 0),
> > + ((0 << 4) | 0),
> > + 0,
> > + 0,
> > + 0,
> > + 0,
> > + 0,
> > + 0,
> > + 0,
> > +};
>
> Can this go at the top of the file? What are the <<4 for ? Can we have
> a #define?
Having that shift as define might get difficult. As you can see this is the value
that gets written into the ddrconf register of the memory scheduler and the
contents of this registers aren't documented in any TRM (rk3288, rk3188,
rk3066).
So I'd like to refrain from introducting possible wrong defines right now :-) .
Heiko
next prev parent reply other threads:[~2017-02-17 20:39 UTC|newest]
Thread overview: 45+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-02-03 16:09 [U-Boot] [PATCH v3 00/16] rk3188 uboot support Heiko Stuebner
2017-02-03 16:09 ` [U-Boot] [PATCH v3 01/16] dm: allow limiting pre-reloc markings to spl or tpl Heiko Stuebner
2017-02-06 15:34 ` Simon Glass
2017-02-17 0:36 ` Heiko Stübner
2017-02-22 3:59 ` Simon Glass
2017-02-03 16:09 ` [U-Boot] [PATCH v3 02/16] rockchip: move bootrom helper compilation to a hidden option Heiko Stuebner
2017-02-06 15:34 ` Simon Glass
2017-02-03 16:09 ` [U-Boot] [PATCH v3 03/16] rockchip: mkimage: Allow encoding of loader code in spl images Heiko Stuebner
2017-02-06 15:35 ` Simon Glass
2017-02-17 3:23 ` Kever Yang
2017-02-03 16:09 ` [U-Boot] [PATCH v3 04/16] rockchip: mkimage: Add support rk3188 serial Heiko Stuebner
2017-02-06 15:35 ` Simon Glass
2017-02-17 3:29 ` Kever Yang
2017-02-03 16:09 ` [U-Boot] [PATCH v3 05/16] rockchip: serial: Adapt rockchip of-platdata driver for rk3188 Heiko Stuebner
2017-02-06 15:35 ` Simon Glass
2017-02-03 16:09 ` [U-Boot] [PATCH v3 06/16] rockchip: rk3188: Add header files for PMU and GRF Heiko Stuebner
2017-02-03 16:09 ` [U-Boot] [PATCH v3 07/16] rockchip: rk3188: Add pinctrl driver Heiko Stuebner
2017-02-03 16:09 ` [U-Boot] [PATCH v3 08/16] rockchip: rk3188: Add sysreset driver Heiko Stuebner
2017-02-06 15:35 ` Simon Glass
2017-02-03 16:09 ` [U-Boot] [PATCH v3 09/16] rockchip: rk3188: Add rk3066/rk3188 clock bindings Heiko Stuebner
2017-02-03 16:09 ` [U-Boot] [PATCH v3 10/16] rockchip: rk3188: Add clock driver Heiko Stuebner
2017-02-06 15:35 ` Simon Glass
2017-02-18 14:19 ` Heiko Stuebner
2017-02-21 18:07 ` Simon Glass
2017-02-21 20:35 ` Simon Glass
2017-02-03 16:09 ` [U-Boot] [PATCH v3 11/16] rockchip: rk3188: Add core devicetree files Heiko Stuebner
2017-02-06 15:35 ` Simon Glass
2017-02-10 23:17 ` Heiko Stuebner
2017-02-03 16:09 ` [U-Boot] [PATCH v3 12/16] rockchip: rk3188: Add core support Heiko Stuebner
2017-02-06 15:35 ` Simon Glass
2017-02-03 16:09 ` [U-Boot] [PATCH v3 13/16] rockchip: rk3188: Add sdram driver Heiko Stuebner
2017-02-06 15:35 ` Simon Glass
2017-02-17 20:39 ` Heiko Stuebner [this message]
2017-02-17 20:44 ` Simon Glass
2017-02-03 16:09 ` [U-Boot] [PATCH v3 14/16] rockchip: rk3188: Add main, spl and tpl boards Heiko Stuebner
2017-02-06 15:35 ` Simon Glass
2017-02-11 0:47 ` Heiko Stuebner
2017-02-03 16:09 ` [U-Boot] [PATCH v3 15/16] rockchip: rk3188: Add Radxa Rock board Heiko Stuebner
2017-02-06 15:35 ` Simon Glass
2017-02-03 16:09 ` [U-Boot] [TEST-ONLY 16/16] Add a temporary script that can create a bootimage for rk3188 Heiko Stuebner
2017-02-06 15:35 ` Simon Glass
2017-02-16 20:43 ` [U-Boot] [PATCH v3 00/16] rk3188 uboot support Simon Glass
2017-02-17 0:41 ` Heiko Stübner
2017-02-17 20:11 ` Heiko Stuebner
2017-02-17 3:21 ` Kever Yang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3647173.obZyHJeQ1U@phil \
--to=heiko@sntech.de \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox