Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/1132726/?format=api
{ "id": 1132726, "url": "http://patchwork.ozlabs.org/api/patches/1132726/?format=api", "web_url": "http://patchwork.ozlabs.org/project/uboot/patch/20190716115745.12585-53-jagan@amarulasolutions.com/", "project": { "id": 18, "url": "http://patchwork.ozlabs.org/api/projects/18/?format=api", "name": "U-Boot", "link_name": "uboot", "list_id": "u-boot.lists.denx.de", "list_email": "u-boot@lists.denx.de", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20190716115745.12585-53-jagan@amarulasolutions.com>", "list_archive_url": null, "date": "2019-07-16T11:57:40", "name": "[U-Boot,v3,52/57] ram: rk3399: Add lpddr4 set rate support", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": false, "hash": "ed334fce8c6851afe1904a0eac771408f2820efb", "submitter": { "id": 69820, "url": "http://patchwork.ozlabs.org/api/people/69820/?format=api", "name": "Jagan Teki", "email": "jagan@amarulasolutions.com" }, "delegate": { "id": 93623, "url": "http://patchwork.ozlabs.org/api/users/93623/?format=api", "username": "kevery", "first_name": "Kever", "last_name": "Yang", "email": "ykai007@gmail.com" }, "mbox": "http://patchwork.ozlabs.org/project/uboot/patch/20190716115745.12585-53-jagan@amarulasolutions.com/mbox/", "series": [ { "id": 119754, "url": "http://patchwork.ozlabs.org/api/series/119754/?format=api", "web_url": "http://patchwork.ozlabs.org/project/uboot/list/?series=119754", "date": "2019-07-16T11:56:48", "name": "ram: rk3399: Add LPDDR4 support", "version": 3, "mbox": "http://patchwork.ozlabs.org/series/119754/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/1132726/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/1132726/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<u-boot-bounces@lists.denx.de>", "X-Original-To": "incoming@patchwork.ozlabs.org", "Delivered-To": "patchwork-incoming@bilbo.ozlabs.org", "Authentication-Results": [ "ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=lists.denx.de\n\t(client-ip=81.169.180.215; helo=lists.denx.de;\n\tenvelope-from=u-boot-bounces@lists.denx.de;\n\treceiver=<UNKNOWN>)", "ozlabs.org; dmarc=none (p=none dis=none)\n\theader.from=amarulasolutions.com", "ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n\tunprotected) header.d=amarulasolutions.com\n\theader.i=@amarulasolutions.com header.b=\"bVH2R1mc\"; \n\tdkim-atps=neutral" ], "Received": [ "from lists.denx.de (dione.denx.de [81.169.180.215])\n\tby ozlabs.org (Postfix) with ESMTP id 45p0293qCJz9s3l\n\tfor <incoming@patchwork.ozlabs.org>;\n\tTue, 16 Jul 2019 22:24:17 +1000 (AEST)", "by lists.denx.de (Postfix, from userid 105)\n\tid EDB94C21E77; Tue, 16 Jul 2019 12:06:50 +0000 (UTC)", "from lists.denx.de (localhost [IPv6:::1])\n\tby lists.denx.de (Postfix) with ESMTP id CD339C21E4F;\n\tTue, 16 Jul 2019 12:04:00 +0000 (UTC)", "by lists.denx.de (Postfix, from userid 105)\n\tid 992B5C21E57; Tue, 16 Jul 2019 12:01:28 +0000 (UTC)", "from mail-pl1-f194.google.com (mail-pl1-f194.google.com\n\t[209.85.214.194])\n\tby lists.denx.de (Postfix) with ESMTPS id 8212EC21E62\n\tfor <u-boot@lists.denx.de>; Tue, 16 Jul 2019 12:01:04 +0000 (UTC)", "by mail-pl1-f194.google.com with SMTP id b7so10010523pls.6\n\tfor <u-boot@lists.denx.de>; Tue, 16 Jul 2019 05:01:04 -0700 (PDT)", "from localhost.localdomain ([49.206.201.107])\n\tby smtp.gmail.com with ESMTPSA id\n\tz24sm36269566pfr.51.2019.07.16.05.00.59\n\t(version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);\n\tTue, 16 Jul 2019 05:01:02 -0700 (PDT)" ], "X-Spam-Checker-Version": "SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de", "X-Spam-Level": "", "X-Spam-Status": "No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3,\n\tRCVD_IN_MSPIKE_WL,\n\tT_DKIM_INVALID autolearn=unavailable autolearn_force=no\n\tversion=3.4.0", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=amarulasolutions.com; s=google;\n\th=from:to:cc:subject:date:message-id:in-reply-to:references\n\t:mime-version:content-transfer-encoding;\n\tbh=VYlEm5rHh1utuucvpfabgypx14dGISV/IEDkNAeLzHg=;\n\tb=bVH2R1mcu3O6j2JC5hhNzYuwBFSMYD25WUjiYgMIgRAOithOVs1SbL6K6XduZnc6hl\n\tT4aEvnRZWz9Kseirwvu7BV4FGujZEk4K9z4VrYr+X8uCTvB6DyaNIG1RQIEONkZihCdy\n\tlJ38v5jhf/muIVaJrO4wn2t3vd1Qz1isRhyN4=", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n\t:references:mime-version:content-transfer-encoding;\n\tbh=VYlEm5rHh1utuucvpfabgypx14dGISV/IEDkNAeLzHg=;\n\tb=lfGVIA8TVRq7XqOOoXjstdO7TsdnsIHaLiBq+K2/b4HPLsZbB0FRN37mN/GVoirNct\n\ta/+27eXjvI2SutXFgJjHMDnIC08fyMYuqE5WqRCgZLeEwMAWQJFE2iq3yxj6MEzHS6L/\n\tZxrUz4O4m7Wi5fvupa152tWKmO0swunM6Qlj/xOv/SiJRmhzBG29VbRgs42eMwSxdksT\n\t/K8zi9yfbDfRnVmew5GdH5a9jyOK12soUdEeUCQOBbg6+HUzuYw01LzS7T93Ovg0DxSA\n\t4cYRAGwq90sXQaw5i9jASZh6eAWAAGzsD0NMjS+eghNmrMOw06Yq1Rp/cmLLy49/mgIM\n\tpWvA==", "X-Gm-Message-State": "APjAAAV4ElCpqH6xQOQ4torCwMA3P8drOqj6jl++9FjxHdK9QyrOUBTk\n\tvZJmqVfwUhX67z4opScssdb8Vw==", "X-Google-Smtp-Source": "APXvYqyQjnRGwJXYO+AGuhAdqseRCk8cmwiSr0iCBjjrQo8qHOV+jTaOEogtClHhAAad/PzHpnI4/A==", "X-Received": "by 2002:a17:902:4401:: with SMTP id\n\tk1mr11449482pld.193.1563278462764; \n\tTue, 16 Jul 2019 05:01:02 -0700 (PDT)", "From": "Jagan Teki <jagan@amarulasolutions.com>", "To": "Simon Glass <sjg@chromium.org>,\n\tPhilipp Tomsich <philipp.tomsich@theobroma-systems.com>,\n\tKever Yang <kever.yang@rock-chips.com>,\n\tYouMin Chen <cym@rock-chips.com>, u-boot@lists.denx.de", "Date": "Tue, 16 Jul 2019 17:27:40 +0530", "Message-Id": "<20190716115745.12585-53-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", "Cc": "linux-rockchip@lists.infradead.org, gajjar04akash@gmail.com,\n\tlinux-amarula@amarulasolutions.com,\n\tManivannan Sadhasivam <manivannan.sadhasivam@linaro.org>", "Subject": "[U-Boot] [PATCH v3 52/57] ram: rk3399: Add lpddr4 set rate support", "X-BeenThere": "u-boot@lists.denx.de", "X-Mailman-Version": "2.1.18", "Precedence": "list", "List-Id": "U-Boot discussion <u-boot.lists.denx.de>", "List-Unsubscribe": "<https://lists.denx.de/options/u-boot>,\n\t<mailto:u-boot-request@lists.denx.de?subject=unsubscribe>", "List-Archive": "<http://lists.denx.de/pipermail/u-boot/>", "List-Post": "<mailto:u-boot@lists.denx.de>", "List-Help": "<mailto:u-boot-request@lists.denx.de?subject=help>", "List-Subscribe": "<https://lists.denx.de/listinfo/u-boot>,\n\t<mailto:u-boot-request@lists.denx.de?subject=subscribe>", "Content-Type": "text/plain; charset=\"utf-8\"", "Content-Transfer-Encoding": "base64", "Errors-To": "u-boot-bounces@lists.denx.de", "Sender": "\"U-Boot\" <u-boot-bounces@lists.denx.de>" }, "content": "Unlike rest of dram type chips, LPDDR4 initialization start\nwith at board selected frequency (say 50MHz) and then it\nswitches into 400MHz and 800MHz simultaneously to make the\nproper sequence work on each channel with associated training.\n\nThe lpddr4 set rate sequnce will follow by setting lpddr4\n- dq out\n- ca odt\n- MR3\n- MR12\n- MR14\nregisters sets in sequential order.\n\nHere is sameple log about LPDDR4-100 init sequence in Rockpro64:\n\nChannel 0: LPDDR4, 50MHz\nBW=32 Col=10 Bk=8 CS0 Row=15 CS1 Row=15 CS=2 Die BW=16 Size=2048MB\nChannel 1: LPDDR4, 50MHz\nBW=32 Col=10 Bk=8 CS0 Row=15 CS1 Row=15 CS=2 Die BW=16 Size=2048MB\n256B stride\nchannel 0 training pass\nchannel 1 training pass\nchange freq to 400 MHz 0, 1\nchannel 0 training pass\nchannel 1 training pass\nchange freq to 800 MHz 1, 0\n\nThis patch add support to this init sequence via lpddr4 set rate\nby taking sdram timing parameters from 400, 800 .inc files.\n\nSigned-off-by: Jagan Teki <jagan@amarulasolutions.com>\nSigned-off-by: YouMin Chen <cym@rock-chips.com>\n---\n drivers/ram/rockchip/sdram_rk3399.c | 677 +++++++++++++++++++++++++++-\n 1 file changed, 665 insertions(+), 12 deletions(-)", "diff": "diff --git a/drivers/ram/rockchip/sdram_rk3399.c b/drivers/ram/rockchip/sdram_rk3399.c\nindex c3d7665ea2..3f29b5e0e8 100644\n--- a/drivers/ram/rockchip/sdram_rk3399.c\n+++ b/drivers/ram/rockchip/sdram_rk3399.c\n@@ -16,6 +16,7 @@\n #include <asm/arch-rockchip/clock.h>\n #include <asm/arch-rockchip/cru_rk3399.h>\n #include <asm/arch-rockchip/grf_rk3399.h>\n+#include <asm/arch-rockchip/pmu_rk3399.h>\n #include <asm/arch-rockchip/hardware.h>\n #include <asm/arch-rockchip/sdram_common.h>\n #include <asm/arch-rockchip/sdram_rk3399.h>\n@@ -62,6 +63,7 @@ struct dram_info {\n \tstruct clk ddr_clk;\n \tstruct rk3399_cru *cru;\n \tstruct rk3399_grf_regs *grf;\n+\tstruct rk3399_pmu_regs *pmu;\n \tstruct rk3399_pmucru *pmucru;\n \tstruct rk3399_pmusgrf_regs *pmusgrf;\n \tstruct rk3399_ddr_cic_regs *cic;\n@@ -75,7 +77,7 @@ struct sdram_rk3399_ops {\n \tint (*data_training)(struct dram_info *dram, u32 channel, u8 rank,\n \t\t\t struct rk3399_sdram_params *sdram);\n \tint (*set_rate)(struct dram_info *dram,\n-\t\t\tconst struct rk3399_sdram_params *params);\n+\t\t\tstruct rk3399_sdram_params *params);\n };\n \n #if defined(CONFIG_TPL_BUILD) || \\\n@@ -221,6 +223,18 @@ lpddr4_get_io_settings(const struct rk3399_sdram_params *params, u32 mr5)\n \treturn io;\n }\n \n+static void *get_denali_phy(const struct chan_info *chan,\n+\t\t\t struct rk3399_sdram_params *params, bool reg)\n+{\n+\treturn reg ? &chan->publ->denali_phy : ¶ms->phy_regs.denali_phy;\n+}\n+\n+static void *get_denali_ctl(const struct chan_info *chan,\n+\t\t\t struct rk3399_sdram_params *params, bool reg)\n+{\n+\treturn reg ? &chan->pctl->denali_ctl : ¶ms->pctl_regs.denali_ctl;\n+}\n+\n static void *get_ddrc0_con(struct dram_info *dram, u8 channel)\n {\n \treturn (channel == 0) ? &dram->grf->ddrc0_con0 : &dram->grf->ddrc0_con1;\n@@ -574,10 +588,11 @@ static int phy_io_config(const struct chan_info *chan,\n }\n \n static void set_ds_odt(const struct chan_info *chan,\n-\t\t const struct rk3399_sdram_params *params, u32 mr5)\n+\t\t struct rk3399_sdram_params *params,\n+\t\t bool ctl_phy_reg, u32 mr5)\n {\n-\tu32 *denali_phy = chan->publ->denali_phy;\n-\tu32 *denali_ctl = chan->pctl->denali_ctl;\n+\tu32 *denali_phy = get_denali_phy(chan, params, ctl_phy_reg);\n+\tu32 *denali_ctl = get_denali_ctl(chan, params, ctl_phy_reg);\n \tu32 tsel_idle_en, tsel_wr_en, tsel_rd_en;\n \tu32 tsel_idle_select_p, tsel_rd_select_p;\n \tu32 tsel_idle_select_n, tsel_rd_select_n;\n@@ -735,7 +750,8 @@ static void set_ds_odt(const struct chan_info *chan,\n \tclrsetbits_le32(&denali_phy[928], 0xff, reg_value);\n \n \t/* phy_pad_rst_drive 8bits DENALI_PHY_937 offset_0 */\n-\tclrsetbits_le32(&denali_phy[937], 0xff, reg_value);\n+\tif (!ctl_phy_reg)\n+\t\tclrsetbits_le32(&denali_phy[937], 0xff, reg_value);\n \n \t/* phy_pad_cke_drive 8bits DENALI_PHY_935 offset_0 */\n \tclrsetbits_le32(&denali_phy[935], 0xff, reg_value);\n@@ -919,7 +935,7 @@ static int pctl_cfg(struct dram_info *dram, const struct chan_info *chan,\n \tcopy_to_reg(&denali_phy[512], ¶ms_phy[512], (549 - 512 + 1) * 4);\n \tcopy_to_reg(&denali_phy[640], ¶ms_phy[640], (677 - 640 + 1) * 4);\n \tcopy_to_reg(&denali_phy[768], ¶ms_phy[768], (805 - 768 + 1) * 4);\n-\tset_ds_odt(chan, params, 0);\n+\tset_ds_odt(chan, params, true, 0);\n \n \t/*\n \t * phy_dqs_tsel_wr_timing_X 8bits DENALI_PHY_84/212/340/468 offset_8\n@@ -950,7 +966,6 @@ static int pctl_cfg(struct dram_info *dram, const struct chan_info *chan,\n \treturn 0;\n }\n \n-#if !defined(CONFIG_RAM_RK3399_LPDDR4)\n static void select_per_cs_training_index(const struct chan_info *chan,\n \t\t\t\t\t u32 rank)\n {\n@@ -1308,7 +1323,7 @@ static int data_training(struct dram_info *dram, u32 channel,\n \n \tif (training_flag == PI_FULL_TRAINING) {\n \t\tif (params->base.dramtype == LPDDR4) {\n-\t\t\ttraining_flag = PI_CA_TRAINING | PI_WRITE_LEVELING |\n+\t\t\ttraining_flag = PI_WRITE_LEVELING |\n \t\t\t\t\tPI_READ_GATE_TRAINING |\n \t\t\t\t\tPI_READ_LEVELING | PI_WDQ_LEVELING;\n \t\t} else if (params->base.dramtype == LPDDR3) {\n@@ -1371,7 +1386,6 @@ static int data_training(struct dram_info *dram, u32 channel,\n \n \treturn 0;\n }\n-#endif\n \n static void set_ddrconfig(const struct chan_info *chan,\n \t\t\t const struct rk3399_sdram_params *params,\n@@ -1493,7 +1507,7 @@ static int default_data_training(struct dram_info *dram, u32 channel, u8 rank,\n }\n \n static int switch_to_phy_index1(struct dram_info *dram,\n-\t\t\t\tconst struct rk3399_sdram_params *params)\n+\t\t\t\tstruct rk3399_sdram_params *params)\n {\n \tu32 channel;\n \tu32 *denali_phy;\n@@ -1539,6 +1553,31 @@ static int switch_to_phy_index1(struct dram_info *dram,\n \n #else\n \n+struct rk3399_sdram_params lpddr4_timings[] = {\n+\t#include \"sdram-rk3399-lpddr4-400.inc\"\n+\t#include \"sdram-rk3399-lpddr4-800.inc\"\n+};\n+\n+static void *get_denali_pi(const struct chan_info *chan,\n+\t\t\t struct rk3399_sdram_params *params, bool reg)\n+{\n+\treturn reg ? &chan->pi->denali_pi : ¶ms->pi_regs.denali_pi;\n+}\n+\n+static u32 lpddr4_get_phy(struct rk3399_sdram_params *params, u32 ctl)\n+{\n+\tu32 lpddr4_phy[] = {1, 0, 0xb};\n+\n+\treturn lpddr4_phy[ctl];\n+}\n+\n+static u32 lpddr4_get_ctl(struct rk3399_sdram_params *params, u32 phy)\n+{\n+\tu32 lpddr4_ctl[] = {1, 0, 2};\n+\n+\treturn lpddr4_ctl[phy];\n+}\n+\n static u32 get_ddr_stride(struct rk3399_pmusgrf_regs *pmusgrf)\n {\n \treturn ((readl(&pmusgrf->soc_con4) >> 10) & 0x1F);\n@@ -1756,6 +1795,618 @@ end:\n \n \treturn ret;\n }\n+\n+static void set_lpddr4_dq_odt(const struct chan_info *chan,\n+\t\t\t struct rk3399_sdram_params *params, u32 ctl,\n+\t\t\t bool en, bool ctl_phy_reg, u32 mr5)\n+{\n+\tu32 *denali_ctl = get_denali_ctl(chan, params, ctl_phy_reg);\n+\tu32 *denali_pi = get_denali_pi(chan, params, ctl_phy_reg);\n+\tstruct io_setting *io;\n+\tu32 reg_value;\n+\n+\tif (!en)\n+\t\treturn;\n+\n+\tio = lpddr4_get_io_settings(params, mr5);\n+\n+\treg_value = io->dq_odt;\n+\n+\tswitch (ctl) {\n+\tcase 0:\n+\t\tclrsetbits_le32(&denali_ctl[139], 0x7 << 24, reg_value << 24);\n+\t\tclrsetbits_le32(&denali_ctl[153], 0x7 << 24, reg_value << 24);\n+\n+\t\tclrsetbits_le32(&denali_pi[132], 0x7 << 0, (reg_value << 0));\n+\t\tclrsetbits_le32(&denali_pi[139], 0x7 << 16, (reg_value << 16));\n+\t\tclrsetbits_le32(&denali_pi[147], 0x7 << 0, (reg_value << 0));\n+\t\tclrsetbits_le32(&denali_pi[154], 0x7 << 16, (reg_value << 16));\n+\t\tbreak;\n+\tcase 1:\n+\t\tclrsetbits_le32(&denali_ctl[140], 0x7 << 0, reg_value << 0);\n+\t\tclrsetbits_le32(&denali_ctl[154], 0x7 << 0, reg_value << 0);\n+\n+\t\tclrsetbits_le32(&denali_pi[129], 0x7 << 16, (reg_value << 16));\n+\t\tclrsetbits_le32(&denali_pi[137], 0x7 << 0, (reg_value << 0));\n+\t\tclrsetbits_le32(&denali_pi[144], 0x7 << 16, (reg_value << 16));\n+\t\tclrsetbits_le32(&denali_pi[152], 0x7 << 0, (reg_value << 0));\n+\t\tbreak;\n+\tcase 2:\n+\tdefault:\n+\t\tclrsetbits_le32(&denali_ctl[140], 0x7 << 8, (reg_value << 8));\n+\t\tclrsetbits_le32(&denali_ctl[154], 0x7 << 8, (reg_value << 8));\n+\n+\t\tclrsetbits_le32(&denali_pi[127], 0x7 << 0, (reg_value << 0));\n+\t\tclrsetbits_le32(&denali_pi[134], 0x7 << 16, (reg_value << 16));\n+\t\tclrsetbits_le32(&denali_pi[142], 0x7 << 0, (reg_value << 0));\n+\t\tclrsetbits_le32(&denali_pi[149], 0x7 << 16, (reg_value << 16));\n+\t\tbreak;\n+\t}\n+}\n+\n+static void set_lpddr4_ca_odt(const struct chan_info *chan,\n+\t\t\t struct rk3399_sdram_params *params, u32 ctl,\n+\t\t\t bool en, bool ctl_phy_reg, u32 mr5)\n+{\n+\tu32 *denali_ctl = get_denali_ctl(chan, params, ctl_phy_reg);\n+\tu32 *denali_pi = get_denali_pi(chan, params, ctl_phy_reg);\n+\tstruct io_setting *io;\n+\tu32 reg_value;\n+\n+\tif (!en)\n+\t\treturn;\n+\n+\tio = lpddr4_get_io_settings(params, mr5);\n+\n+\treg_value = io->ca_odt;\n+\n+\tswitch (ctl) {\n+\tcase 0:\n+\t\tclrsetbits_le32(&denali_ctl[139], 0x7 << 28, reg_value << 28);\n+\t\tclrsetbits_le32(&denali_ctl[153], 0x7 << 28, reg_value << 28);\n+\n+\t\tclrsetbits_le32(&denali_pi[132], 0x7 << 4, reg_value << 4);\n+\t\tclrsetbits_le32(&denali_pi[139], 0x7 << 20, reg_value << 20);\n+\t\tclrsetbits_le32(&denali_pi[147], 0x7 << 4, reg_value << 4);\n+\t\tclrsetbits_le32(&denali_pi[154], 0x7 << 20, reg_value << 20);\n+\t\tbreak;\n+\tcase 1:\n+\t\tclrsetbits_le32(&denali_ctl[140], 0x7 << 4, reg_value << 4);\n+\t\tclrsetbits_le32(&denali_ctl[154], 0x7 << 4, reg_value << 4);\n+\n+\t\tclrsetbits_le32(&denali_pi[129], 0x7 << 20, reg_value << 20);\n+\t\tclrsetbits_le32(&denali_pi[137], 0x7 << 4, reg_value << 4);\n+\t\tclrsetbits_le32(&denali_pi[144], 0x7 << 20, reg_value << 20);\n+\t\tclrsetbits_le32(&denali_pi[152], 0x7 << 4, reg_value << 4);\n+\t\tbreak;\n+\tcase 2:\n+\tdefault:\n+\t\tclrsetbits_le32(&denali_ctl[140], 0x7 << 12, (reg_value << 12));\n+\t\tclrsetbits_le32(&denali_ctl[154], 0x7 << 12, (reg_value << 12));\n+\n+\t\tclrsetbits_le32(&denali_pi[127], 0x7 << 4, reg_value << 4);\n+\t\tclrsetbits_le32(&denali_pi[134], 0x7 << 20, reg_value << 20);\n+\t\tclrsetbits_le32(&denali_pi[142], 0x7 << 4, reg_value << 4);\n+\t\tclrsetbits_le32(&denali_pi[149], 0x7 << 20, reg_value << 20);\n+\t\tbreak;\n+\t}\n+}\n+\n+static void set_lpddr4_MR3(const struct chan_info *chan,\n+\t\t\t struct rk3399_sdram_params *params, u32 ctl,\n+\t\t\t bool ctl_phy_reg, u32 mr5)\n+{\n+\tu32 *denali_ctl = get_denali_ctl(chan, params, ctl_phy_reg);\n+\tu32 *denali_pi = get_denali_pi(chan, params, ctl_phy_reg);\n+\tstruct io_setting *io;\n+\tu32 reg_value;\n+\n+\tio = lpddr4_get_io_settings(params, mr5);\n+\n+\treg_value = ((io->pdds << 3) | 1);\n+\n+\tswitch (ctl) {\n+\tcase 0:\n+\t\tclrsetbits_le32(&denali_ctl[138], 0xFFFF, reg_value);\n+\t\tclrsetbits_le32(&denali_ctl[152], 0xFFFF, reg_value);\n+\n+\t\tclrsetbits_le32(&denali_pi[131], 0xFFFF << 16, reg_value << 16);\n+\t\tclrsetbits_le32(&denali_pi[139], 0xFFFF, reg_value);\n+\t\tclrsetbits_le32(&denali_pi[146], 0xFFFF << 16, reg_value << 16);\n+\t\tclrsetbits_le32(&denali_pi[154], 0xFFFF, reg_value);\n+\t\tbreak;\n+\tcase 1:\n+\t\tclrsetbits_le32(&denali_ctl[138], 0xFFFF << 16,\n+\t\t\t\treg_value << 16);\n+\t\tclrsetbits_le32(&denali_ctl[152], 0xFFFF << 16,\n+\t\t\t\treg_value << 16);\n+\n+\t\tclrsetbits_le32(&denali_pi[129], 0xFFFF, reg_value);\n+\t\tclrsetbits_le32(&denali_pi[136], 0xFFFF << 16, reg_value << 16);\n+\t\tclrsetbits_le32(&denali_pi[144], 0xFFFF, reg_value);\n+\t\tclrsetbits_le32(&denali_pi[151], 0xFFFF << 16, reg_value << 16);\n+\t\tbreak;\n+\tcase 2:\n+\tdefault:\n+\t\tclrsetbits_le32(&denali_ctl[139], 0xFFFF, reg_value);\n+\t\tclrsetbits_le32(&denali_ctl[153], 0xFFFF, reg_value);\n+\n+\t\tclrsetbits_le32(&denali_pi[126], 0xFFFF << 16, reg_value << 16);\n+\t\tclrsetbits_le32(&denali_pi[134], 0xFFFF, reg_value);\n+\t\tclrsetbits_le32(&denali_pi[141], 0xFFFF << 16, reg_value << 16);\n+\t\tclrsetbits_le32(&denali_pi[149], 0xFFFF, reg_value);\n+\t\tbreak;\n+\t}\n+}\n+\n+static void set_lpddr4_MR12(const struct chan_info *chan,\n+\t\t\t struct rk3399_sdram_params *params, u32 ctl,\n+\t\t\t bool ctl_phy_reg, u32 mr5)\n+{\n+\tu32 *denali_ctl = get_denali_ctl(chan, params, ctl_phy_reg);\n+\tu32 *denali_pi = get_denali_pi(chan, params, ctl_phy_reg);\n+\tstruct io_setting *io;\n+\tu32 reg_value;\n+\n+\tio = lpddr4_get_io_settings(params, mr5);\n+\n+\treg_value = io->ca_vref;\n+\n+\tswitch (ctl) {\n+\tcase 0:\n+\t\tclrsetbits_le32(&denali_ctl[140], 0xFFFF << 16,\n+\t\t\t\treg_value << 16);\n+\t\tclrsetbits_le32(&denali_ctl[154], 0xFFFF << 16,\n+\t\t\t\treg_value << 16);\n+\n+\t\tclrsetbits_le32(&denali_pi[132], 0xFF << 8, reg_value << 8);\n+\t\tclrsetbits_le32(&denali_pi[139], 0xFF << 24, reg_value << 24);\n+\t\tclrsetbits_le32(&denali_pi[147], 0xFF << 8, reg_value << 8);\n+\t\tclrsetbits_le32(&denali_pi[154], 0xFF << 24, reg_value << 24);\n+\t\tbreak;\n+\tcase 1:\n+\t\tclrsetbits_le32(&denali_ctl[141], 0xFFFF, reg_value);\n+\t\tclrsetbits_le32(&denali_ctl[155], 0xFFFF, reg_value);\n+\n+\t\tclrsetbits_le32(&denali_pi[129], 0xFF << 24, reg_value << 24);\n+\t\tclrsetbits_le32(&denali_pi[137], 0xFF << 8, reg_value << 8);\n+\t\tclrsetbits_le32(&denali_pi[144], 0xFF << 24, reg_value << 24);\n+\t\tclrsetbits_le32(&denali_pi[152], 0xFF << 8, reg_value << 8);\n+\t\tbreak;\n+\tcase 2:\n+\tdefault:\n+\t\tclrsetbits_le32(&denali_ctl[141], 0xFFFF << 16,\n+\t\t\t\treg_value << 16);\n+\t\tclrsetbits_le32(&denali_ctl[155], 0xFFFF << 16,\n+\t\t\t\treg_value << 16);\n+\n+\t\tclrsetbits_le32(&denali_pi[127], 0xFF << 8, reg_value << 8);\n+\t\tclrsetbits_le32(&denali_pi[134], 0xFF << 24, reg_value << 24);\n+\t\tclrsetbits_le32(&denali_pi[142], 0xFF << 8, reg_value << 8);\n+\t\tclrsetbits_le32(&denali_pi[149], 0xFF << 24, reg_value << 24);\n+\t\tbreak;\n+\t}\n+}\n+\n+static void set_lpddr4_MR14(const struct chan_info *chan,\n+\t\t\t struct rk3399_sdram_params *params, u32 ctl,\n+\t\t\t bool ctl_phy_reg, u32 mr5)\n+{\n+\tu32 *denali_ctl = get_denali_ctl(chan, params, ctl_phy_reg);\n+\tu32 *denali_pi = get_denali_pi(chan, params, ctl_phy_reg);\n+\tstruct io_setting *io;\n+\tu32 reg_value;\n+\n+\tio = lpddr4_get_io_settings(params, mr5);\n+\n+\treg_value = io->dq_vref;\n+\n+\tswitch (ctl) {\n+\tcase 0:\n+\t\tclrsetbits_le32(&denali_ctl[142], 0xFFFF << 16,\n+\t\t\t\treg_value << 16);\n+\t\tclrsetbits_le32(&denali_ctl[156], 0xFFFF << 16,\n+\t\t\t\treg_value << 16);\n+\n+\t\tclrsetbits_le32(&denali_pi[132], 0xFF << 16, reg_value << 16);\n+\t\tclrsetbits_le32(&denali_pi[140], 0xFF << 0, reg_value << 0);\n+\t\tclrsetbits_le32(&denali_pi[147], 0xFF << 16, reg_value << 16);\n+\t\tclrsetbits_le32(&denali_pi[155], 0xFF << 0, reg_value << 0);\n+\t\tbreak;\n+\tcase 1:\n+\t\tclrsetbits_le32(&denali_ctl[143], 0xFFFF, reg_value);\n+\t\tclrsetbits_le32(&denali_ctl[157], 0xFFFF, reg_value);\n+\n+\t\tclrsetbits_le32(&denali_pi[130], 0xFF << 0, reg_value << 0);\n+\t\tclrsetbits_le32(&denali_pi[137], 0xFF << 16, reg_value << 16);\n+\t\tclrsetbits_le32(&denali_pi[145], 0xFF << 0, reg_value << 0);\n+\t\tclrsetbits_le32(&denali_pi[152], 0xFF << 16, reg_value << 16);\n+\t\tbreak;\n+\tcase 2:\n+\tdefault:\n+\t\tclrsetbits_le32(&denali_ctl[143], 0xFFFF << 16,\n+\t\t\t\treg_value << 16);\n+\t\tclrsetbits_le32(&denali_ctl[157], 0xFFFF << 16,\n+\t\t\t\treg_value << 16);\n+\n+\t\tclrsetbits_le32(&denali_pi[127], 0xFF << 16, reg_value << 16);\n+\t\tclrsetbits_le32(&denali_pi[135], 0xFF << 0, reg_value << 0);\n+\t\tclrsetbits_le32(&denali_pi[142], 0xFF << 16, reg_value << 16);\n+\t\tclrsetbits_le32(&denali_pi[150], 0xFF << 0, reg_value << 0);\n+\t\tbreak;\n+\t}\n+}\n+\n+static void lpddr4_copy_phy(struct dram_info *dram,\n+\t\t\t struct rk3399_sdram_params *params, u32 phy,\n+\t\t\t struct rk3399_sdram_params *timings,\n+\t\t\t u32 channel)\n+{\n+\tu32 *denali_ctl, *denali_phy;\n+\tu32 *denali_phy_params;\n+\tu32 speed = 0;\n+\tu32 ctl, mr5;\n+\n+\tdenali_ctl = dram->chan[channel].pctl->denali_ctl;\n+\tdenali_phy = dram->chan[channel].publ->denali_phy;\n+\tdenali_phy_params = timings->phy_regs.denali_phy;\n+\n+\t/* switch index */\n+\tclrsetbits_le32(&denali_phy_params[896], 0x3 << 8, phy << 8);\n+\twritel(denali_phy_params[896], &denali_phy[896]);\n+\n+\t/* phy_pll_ctrl_ca, phy_pll_ctrl */\n+\twritel(denali_phy_params[911], &denali_phy[911]);\n+\n+\t/* phy_low_freq_sel */\n+\tclrsetbits_le32(&denali_phy[913], 0x1,\n+\t\t\tdenali_phy_params[913] & 0x1);\n+\n+\t/* phy_grp_slave_delay_x, phy_cslvl_dly_step */\n+\twritel(denali_phy_params[916], &denali_phy[916]);\n+\twritel(denali_phy_params[917], &denali_phy[917]);\n+\twritel(denali_phy_params[918], &denali_phy[918]);\n+\n+\t/* phy_adrz_sw_wraddr_shift_x */\n+\twritel(denali_phy_params[512], &denali_phy[512]);\n+\tclrsetbits_le32(&denali_phy[513], 0xffff,\n+\t\t\tdenali_phy_params[513] & 0xffff);\n+\twritel(denali_phy_params[640], &denali_phy[640]);\n+\tclrsetbits_le32(&denali_phy[641], 0xffff,\n+\t\t\tdenali_phy_params[641] & 0xffff);\n+\twritel(denali_phy_params[768], &denali_phy[768]);\n+\tclrsetbits_le32(&denali_phy[769], 0xffff,\n+\t\t\tdenali_phy_params[769] & 0xffff);\n+\n+\twritel(denali_phy_params[544], &denali_phy[544]);\n+\twritel(denali_phy_params[545], &denali_phy[545]);\n+\twritel(denali_phy_params[546], &denali_phy[546]);\n+\twritel(denali_phy_params[547], &denali_phy[547]);\n+\n+\twritel(denali_phy_params[672], &denali_phy[672]);\n+\twritel(denali_phy_params[673], &denali_phy[673]);\n+\twritel(denali_phy_params[674], &denali_phy[674]);\n+\twritel(denali_phy_params[675], &denali_phy[675]);\n+\n+\twritel(denali_phy_params[800], &denali_phy[800]);\n+\twritel(denali_phy_params[801], &denali_phy[801]);\n+\twritel(denali_phy_params[802], &denali_phy[802]);\n+\twritel(denali_phy_params[803], &denali_phy[803]);\n+\n+\t/*\n+\t * phy_adr_master_delay_start_x\n+\t * phy_adr_master_delay_step_x\n+\t * phy_adr_master_delay_wait_x\n+\t */\n+\twritel(denali_phy_params[548], &denali_phy[548]);\n+\twritel(denali_phy_params[676], &denali_phy[676]);\n+\twritel(denali_phy_params[804], &denali_phy[804]);\n+\n+\t/* phy_adr_calvl_dly_step_x */\n+\twritel(denali_phy_params[549], &denali_phy[549]);\n+\twritel(denali_phy_params[677], &denali_phy[677]);\n+\twritel(denali_phy_params[805], &denali_phy[805]);\n+\n+\t/*\n+\t * phy_clk_wrdm_slave_delay_x\n+\t * phy_clk_wrdqz_slave_delay_x\n+\t * phy_clk_wrdqs_slave_delay_x\n+\t */\n+\tcopy_to_reg((u32 *)&denali_phy[59], (u32 *)&denali_phy_params[59],\n+\t\t (63 - 58) * 4);\n+\tcopy_to_reg((u32 *)&denali_phy[187], (u32 *)&denali_phy_params[187],\n+\t\t (191 - 186) * 4);\n+\tcopy_to_reg((u32 *)&denali_phy[315], (u32 *)&denali_phy_params[315],\n+\t\t (319 - 314) * 4);\n+\tcopy_to_reg((u32 *)&denali_phy[443], (u32 *)&denali_phy_params[443],\n+\t\t (447 - 442) * 4);\n+\n+\t/*\n+\t * phy_dqs_tsel_wr_timing_x 8bits denali_phy_84/212/340/468 offset_8\n+\t * dqs_tsel_wr_end[7:4] add half cycle\n+\t * phy_dq_tsel_wr_timing_x 8bits denali_phy_83/211/339/467 offset_8\n+\t * dq_tsel_wr_end[7:4] add half cycle\n+\t */\n+\twritel(denali_phy_params[83] + (0x10 << 16), &denali_phy[83]);\n+\twritel(denali_phy_params[84] + (0x10 << 8), &denali_phy[84]);\n+\twritel(denali_phy_params[85], &denali_phy[85]);\n+\n+\twritel(denali_phy_params[211] + (0x10 << 16), &denali_phy[211]);\n+\twritel(denali_phy_params[212] + (0x10 << 8), &denali_phy[212]);\n+\twritel(denali_phy_params[213], &denali_phy[213]);\n+\n+\twritel(denali_phy_params[339] + (0x10 << 16), &denali_phy[339]);\n+\twritel(denali_phy_params[340] + (0x10 << 8), &denali_phy[340]);\n+\twritel(denali_phy_params[341], &denali_phy[341]);\n+\n+\twritel(denali_phy_params[467] + (0x10 << 16), &denali_phy[467]);\n+\twritel(denali_phy_params[468] + (0x10 << 8), &denali_phy[468]);\n+\twritel(denali_phy_params[469], &denali_phy[469]);\n+\n+\t/*\n+\t * phy_gtlvl_resp_wait_cnt_x\n+\t * phy_gtlvl_dly_step_x\n+\t * phy_wrlvl_resp_wait_cnt_x\n+\t * phy_gtlvl_final_step_x\n+\t * phy_gtlvl_back_step_x\n+\t * phy_rdlvl_dly_step_x\n+\t *\n+\t * phy_master_delay_step_x\n+\t * phy_master_delay_wait_x\n+\t * phy_wrlvl_dly_step_x\n+\t * phy_rptr_update_x\n+\t * phy_wdqlvl_dly_step_x\n+\t */\n+\twritel(denali_phy_params[87], &denali_phy[87]);\n+\twritel(denali_phy_params[88], &denali_phy[88]);\n+\twritel(denali_phy_params[89], &denali_phy[89]);\n+\twritel(denali_phy_params[90], &denali_phy[90]);\n+\n+\twritel(denali_phy_params[215], &denali_phy[215]);\n+\twritel(denali_phy_params[216], &denali_phy[216]);\n+\twritel(denali_phy_params[217], &denali_phy[217]);\n+\twritel(denali_phy_params[218], &denali_phy[218]);\n+\n+\twritel(denali_phy_params[343], &denali_phy[343]);\n+\twritel(denali_phy_params[344], &denali_phy[344]);\n+\twritel(denali_phy_params[345], &denali_phy[345]);\n+\twritel(denali_phy_params[346], &denali_phy[346]);\n+\n+\twritel(denali_phy_params[471], &denali_phy[471]);\n+\twritel(denali_phy_params[472], &denali_phy[472]);\n+\twritel(denali_phy_params[473], &denali_phy[473]);\n+\twritel(denali_phy_params[474], &denali_phy[474]);\n+\n+\t/*\n+\t * phy_gtlvl_lat_adj_start_x\n+\t * phy_gtlvl_rddqs_slv_dly_start_x\n+\t * phy_rdlvl_rddqs_dq_slv_dly_start_x\n+\t * phy_wdqlvl_dqdm_slv_dly_start_x\n+\t */\n+\twritel(denali_phy_params[80], &denali_phy[80]);\n+\twritel(denali_phy_params[81], &denali_phy[81]);\n+\n+\twritel(denali_phy_params[208], &denali_phy[208]);\n+\twritel(denali_phy_params[209], &denali_phy[209]);\n+\n+\twritel(denali_phy_params[336], &denali_phy[336]);\n+\twritel(denali_phy_params[337], &denali_phy[337]);\n+\n+\twritel(denali_phy_params[464], &denali_phy[464]);\n+\twritel(denali_phy_params[465], &denali_phy[465]);\n+\n+\t/*\n+\t * phy_master_delay_start_x\n+\t * phy_sw_master_mode_x\n+\t * phy_rddata_en_tsel_dly_x\n+\t */\n+\twritel(denali_phy_params[86], &denali_phy[86]);\n+\twritel(denali_phy_params[214], &denali_phy[214]);\n+\twritel(denali_phy_params[342], &denali_phy[342]);\n+\twritel(denali_phy_params[470], &denali_phy[470]);\n+\n+\t/*\n+\t * phy_rddqz_slave_delay_x\n+\t * phy_rddqs_dqz_fall_slave_delay_x\n+\t * phy_rddqs_dqz_rise_slave_delay_x\n+\t * phy_rddqs_dm_fall_slave_delay_x\n+\t * phy_rddqs_dm_rise_slave_delay_x\n+\t * phy_rddqs_gate_slave_delay_x\n+\t * phy_wrlvl_delay_early_threshold_x\n+\t * phy_write_path_lat_add_x\n+\t * phy_rddqs_latency_adjust_x\n+\t * phy_wrlvl_delay_period_threshold_x\n+\t * phy_wrlvl_early_force_zero_x\n+\t */\n+\tcopy_to_reg((u32 *)&denali_phy[64], (u32 *)&denali_phy_params[64],\n+\t\t (67 - 63) * 4);\n+\tclrsetbits_le32(&denali_phy[68], 0xfffffc00,\n+\t\t\tdenali_phy_params[68] & 0xfffffc00);\n+\tcopy_to_reg((u32 *)&denali_phy[69], (u32 *)&denali_phy_params[69],\n+\t\t (79 - 68) * 4);\n+\tcopy_to_reg((u32 *)&denali_phy[192], (u32 *)&denali_phy_params[192],\n+\t\t (195 - 191) * 4);\n+\tclrsetbits_le32(&denali_phy[196], 0xfffffc00,\n+\t\t\tdenali_phy_params[196] & 0xfffffc00);\n+\tcopy_to_reg((u32 *)&denali_phy[197], (u32 *)&denali_phy_params[197],\n+\t\t (207 - 196) * 4);\n+\tcopy_to_reg((u32 *)&denali_phy[320], (u32 *)&denali_phy_params[320],\n+\t\t (323 - 319) * 4);\n+\tclrsetbits_le32(&denali_phy[324], 0xfffffc00,\n+\t\t\tdenali_phy_params[324] & 0xfffffc00);\n+\tcopy_to_reg((u32 *)&denali_phy[325], (u32 *)&denali_phy_params[325],\n+\t\t (335 - 324) * 4);\n+\n+\tcopy_to_reg((u32 *)&denali_phy[448], (u32 *)&denali_phy_params[448],\n+\t\t (451 - 447) * 4);\n+\tclrsetbits_le32(&denali_phy[452], 0xfffffc00,\n+\t\t\tdenali_phy_params[452] & 0xfffffc00);\n+\tcopy_to_reg((u32 *)&denali_phy[453], (u32 *)&denali_phy_params[453],\n+\t\t (463 - 452) * 4);\n+\n+\t/* phy_two_cyc_preamble_x */\n+\tclrsetbits_le32(&denali_phy[7], 0x3 << 24,\n+\t\t\tdenali_phy_params[7] & (0x3 << 24));\n+\tclrsetbits_le32(&denali_phy[135], 0x3 << 24,\n+\t\t\tdenali_phy_params[135] & (0x3 << 24));\n+\tclrsetbits_le32(&denali_phy[263], 0x3 << 24,\n+\t\t\tdenali_phy_params[263] & (0x3 << 24));\n+\tclrsetbits_le32(&denali_phy[391], 0x3 << 24,\n+\t\t\tdenali_phy_params[391] & (0x3 << 24));\n+\n+\t/* speed */\n+\tif (timings->base.ddr_freq < 400 * MHz)\n+\t\tspeed = 0x0;\n+\telse if (timings->base.ddr_freq < 800 * MHz)\n+\t\tspeed = 0x1;\n+\telse if (timings->base.ddr_freq < 1200 * MHz)\n+\t\tspeed = 0x2;\n+\n+\t/* phy_924 phy_pad_fdbk_drive */\n+\tclrsetbits_le32(&denali_phy[924], 0x3 << 21, speed << 21);\n+\t/* phy_926 phy_pad_data_drive */\n+\tclrsetbits_le32(&denali_phy[926], 0x3 << 9, speed << 9);\n+\t/* phy_927 phy_pad_dqs_drive */\n+\tclrsetbits_le32(&denali_phy[927], 0x3 << 9, speed << 9);\n+\t/* phy_928 phy_pad_addr_drive */\n+\tclrsetbits_le32(&denali_phy[928], 0x3 << 17, speed << 17);\n+\t/* phy_929 phy_pad_clk_drive */\n+\tclrsetbits_le32(&denali_phy[929], 0x3 << 17, speed << 17);\n+\t/* phy_935 phy_pad_cke_drive */\n+\tclrsetbits_le32(&denali_phy[935], 0x3 << 17, speed << 17);\n+\t/* phy_937 phy_pad_rst_drive */\n+\tclrsetbits_le32(&denali_phy[937], 0x3 << 17, speed << 17);\n+\t/* phy_939 phy_pad_cs_drive */\n+\tclrsetbits_le32(&denali_phy[939], 0x3 << 17, speed << 17);\n+\n+\tread_mr(dram->chan[channel].pctl, 1, 5, &mr5);\n+\tset_ds_odt(&dram->chan[channel], timings, true, mr5);\n+\n+\tctl = lpddr4_get_ctl(timings, phy);\n+\tset_lpddr4_dq_odt(&dram->chan[channel], timings, ctl, true, true, mr5);\n+\tset_lpddr4_ca_odt(&dram->chan[channel], timings, ctl, true, true, mr5);\n+\tset_lpddr4_MR3(&dram->chan[channel], timings, ctl, true, mr5);\n+\tset_lpddr4_MR12(&dram->chan[channel], timings, ctl, true, mr5);\n+\tset_lpddr4_MR14(&dram->chan[channel], timings, ctl, true, mr5);\n+\n+\t/*\n+\t * if phy_sw_master_mode_x not bypass mode,\n+\t * clear phy_slice_pwr_rdc_disable.\n+\t * note: need use timings, not ddr_publ_regs\n+\t */\n+\tif (!((denali_phy_params[86] >> 8) & (1 << 2))) {\n+\t\tclrbits_le32(&denali_phy[10], 1 << 16);\n+\t\tclrbits_le32(&denali_phy[138], 1 << 16);\n+\t\tclrbits_le32(&denali_phy[266], 1 << 16);\n+\t\tclrbits_le32(&denali_phy[394], 1 << 16);\n+\t}\n+\n+\t/*\n+\t * when PHY_PER_CS_TRAINING_EN=1, W2W_DIFFCS_DLY_Fx can't\n+\t * smaller than 8\n+\t * NOTE: need use timings, not ddr_publ_regs\n+\t */\n+\tif ((denali_phy_params[84] >> 16) & 1) {\n+\t\tif (((readl(&denali_ctl[217 + ctl]) >> 16) & 0x1f) < 8)\n+\t\t\tclrsetbits_le32(&denali_ctl[217 + ctl],\n+\t\t\t\t\t0x1f << 16, 8 << 16);\n+\t}\n+}\n+\n+static void lpddr4_set_phy(struct dram_info *dram,\n+\t\t\t struct rk3399_sdram_params *params, u32 phy,\n+\t\t\t struct rk3399_sdram_params *timings)\n+{\n+\tu32 channel;\n+\n+\tfor (channel = 0; channel < 2; channel++)\n+\t\tlpddr4_copy_phy(dram, params, phy, timings, channel);\n+}\n+\n+static int lpddr4_set_ctl(struct dram_info *dram,\n+\t\t\t struct rk3399_sdram_params *params, u32 ctl, u32 hz)\n+{\n+\tu32 channel;\n+\tint ret_clk, ret[2];\n+\n+\t/* cci idle req stall */\n+\twritel(0x70007, &dram->grf->soc_con0);\n+\n+\t/* enable all clk */\n+\tsetbits_le32(&dram->pmu->pmu_noc_auto_ena, (0x3 << 7));\n+\n+\t/* idle */\n+\tsetbits_le32(&dram->pmu->pmu_bus_idle_req, (0x3 << 18));\n+\twhile ((readl(&dram->pmu->pmu_bus_idle_st) & (0x3 << 18))\n+\t != (0x3 << 18))\n+\t\t;\n+\n+\t/* change freq */\n+\twritel((((0x3 << 4) | (1 << 2) | 1) << 16) |\n+\t\t(ctl << 4) | (1 << 2) | 1, &dram->cic->cic_ctrl0);\n+\twhile (!(readl(&dram->cic->cic_status0) & (1 << 2)))\n+\t\t;\n+\n+\tret_clk = clk_set_rate(&dram->ddr_clk, hz);\n+\tif (ret_clk < 0) {\n+\t\tprintf(\"%s clk set failed %d\\n\", __func__, ret_clk);\n+\t\treturn ret_clk;\n+\t}\n+\n+\twritel(0x20002, &dram->cic->cic_ctrl0);\n+\twhile (!(readl(&dram->cic->cic_status0) & (1 << 0)))\n+\t\t;\n+\n+\t/* deidle */\n+\tclrbits_le32(&dram->pmu->pmu_bus_idle_req, (0x3 << 18));\n+\twhile (readl(&dram->pmu->pmu_bus_idle_st) & (0x3 << 18))\n+\t\t;\n+\n+\t/* clear enable all clk */\n+\tclrbits_le32(&dram->pmu->pmu_noc_auto_ena, (0x3 << 7));\n+\n+\t/* lpddr4 ctl2 can not do training, all training will fail */\n+\tif (!(params->base.dramtype == LPDDR4 && ctl == 2)) {\n+\t\tfor (channel = 0; channel < 2; channel++) {\n+\t\t\tif (!(params->ch[channel].cap_info.col))\n+\t\t\t\tcontinue;\n+\t\t\tret[channel] = data_training(dram, channel, params,\n+\t\t\t\t\t\t PI_FULL_TRAINING);\n+\t\t}\n+\t\tfor (channel = 0; channel < 2; channel++) {\n+\t\t\tif (!(params->ch[channel].cap_info.col))\n+\t\t\t\tcontinue;\n+\t\t\tif (ret[channel])\n+\t\t\t\tprintf(\"%s: channel %d training failed!\\n\",\n+\t\t\t\t __func__, channel);\n+\t\t\telse\n+\t\t\t\tdebug(\"%s: channel %d training pass\\n\",\n+\t\t\t\t __func__, channel);\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int lpddr4_set_rate(struct dram_info *dram,\n+\t\t\t struct rk3399_sdram_params *params)\n+{\n+\tu32 ctl;\n+\tu32 phy;\n+\n+\tfor (ctl = 0; ctl < 2; ctl++) {\n+\t\tphy = lpddr4_get_phy(params, ctl);\n+\n+\t\tlpddr4_set_phy(dram, params, phy, &lpddr4_timings[ctl]);\n+\t\tlpddr4_set_ctl(dram, params, ctl,\n+\t\t\t lpddr4_timings[ctl].base.ddr_freq);\n+\n+\t\tdebug(\"%s: change freq to %d mhz %d, %d\\n\", __func__,\n+\t\t lpddr4_timings[ctl].base.ddr_freq / MHz, ctl, phy);\n+\t}\n+\n+\treturn 0;\n+}\n #endif /* CONFIG_RAM_RK3399_LPDDR4 */\n \n static unsigned char calculate_stride(struct rk3399_sdram_params *params)\n@@ -1993,6 +2644,7 @@ static const struct sdram_rk3399_ops rk3399_ops = {\n \t.set_rate = switch_to_phy_index1,\n #else\n \t.data_training = lpddr4_mr_detect,\n+\t.set_rate = lpddr4_set_rate,\n #endif\n };\n \n@@ -2016,6 +2668,7 @@ static int rk3399_dmc_init(struct udevice *dev)\n \tpriv->ops = &rk3399_ops;\n \tpriv->cic = syscon_get_first_range(ROCKCHIP_SYSCON_CIC);\n \tpriv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);\n+\tpriv->pmu = syscon_get_first_range(ROCKCHIP_SYSCON_PMU);\n \tpriv->pmugrf = syscon_get_first_range(ROCKCHIP_SYSCON_PMUGRF);\n \tpriv->pmusgrf = syscon_get_first_range(ROCKCHIP_SYSCON_PMUSGRF);\n \tpriv->pmucru = rockchip_get_pmucru();\n@@ -2034,8 +2687,8 @@ static int rk3399_dmc_init(struct udevice *dev)\n \t priv->chan[0].publ, priv->chan[0].msch,\n \t priv->chan[1].pctl, priv->chan[1].pi,\n \t priv->chan[1].publ, priv->chan[1].msch);\n-\tdebug(\"cru %p, cic %p, grf %p, sgrf %p, pmucru %p\\n\", priv->cru,\n-\t priv->cic, priv->pmugrf, priv->pmusgrf, priv->pmucru);\n+\tdebug(\"cru %p, cic %p, grf %p, sgrf %p, pmucru %p, pmu %p\\n\", priv->cru,\n+\t priv->cic, priv->pmugrf, priv->pmusgrf, priv->pmucru, priv->pmu);\n \n #if CONFIG_IS_ENABLED(OF_PLATDATA)\n \tret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &priv->ddr_clk);\n", "prefixes": [ "U-Boot", "v3", "52/57" ] }