diff options
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-uniphier/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/mach-uniphier/dram/cmd_ddrmphy.c | 237 | ||||
-rw-r--r-- | arch/arm/mach-uniphier/dram/cmd_ddrphy.c | 156 | ||||
-rw-r--r-- | arch/arm/mach-uniphier/dram/ddrmphy-regs.h | 264 | ||||
-rw-r--r-- | arch/arm/mach-uniphier/dram/umc-ld20.c | 254 | ||||
-rw-r--r-- | arch/arm/mach-uniphier/dram/umc-pxs2.c | 253 | ||||
-rw-r--r-- | arch/arm/mach-uniphier/dram_init.c | 267 | ||||
-rw-r--r-- | arch/arm/mach-uniphier/init.h | 1 |
8 files changed, 764 insertions, 670 deletions
diff --git a/arch/arm/mach-uniphier/Makefile b/arch/arm/mach-uniphier/Makefile index abfdccc..166b41f 100644 --- a/arch/arm/mach-uniphier/Makefile +++ b/arch/arm/mach-uniphier/Makefile @@ -4,6 +4,7 @@ ifdef CONFIG_SPL_BUILD +obj-y += boards.o obj-y += spl_board_init.o obj-y += memconf.o obj-y += bcu/ @@ -21,7 +22,6 @@ obj-y += pinctrl-glue.o endif -obj-y += boards.o obj-y += soc-info.o obj-y += boot-mode/ obj-y += clk/ diff --git a/arch/arm/mach-uniphier/dram/cmd_ddrmphy.c b/arch/arm/mach-uniphier/dram/cmd_ddrmphy.c index 47cee6f..873dad2 100644 --- a/arch/arm/mach-uniphier/dram/cmd_ddrmphy.c +++ b/arch/arm/mach-uniphier/dram/cmd_ddrmphy.c @@ -1,13 +1,15 @@ /* - * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * Copyright (C) 2015-2017 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> * * SPDX-License-Identifier: GPL-2.0+ */ #include <common.h> #include <linux/io.h> +#include <linux/sizes.h> -#include "../init.h" +#include "../soc-info.h" #include "ddrmphy-regs.h" /* Select either decimal or hexadecimal */ @@ -19,24 +21,41 @@ /* field separator */ #define FS " " -static void __iomem *get_phy_base(int ch) -{ - return (void __iomem *)(0x5b830000 + ch * 0x00200000); -} - -static int get_nr_ch(void) -{ - const struct uniphier_board_data *bd = uniphier_get_board_param(); - - return bd->dram_ch[2].size ? 3 : 2; -} - -static int get_nr_datx8(int ch) -{ - const struct uniphier_board_data *bd = uniphier_get_board_param(); - - return bd->dram_ch[ch].width / 8; -} +#define ptr_to_uint(p) ((unsigned int)(unsigned long)(p)) + +#define UNIPHIER_MAX_NR_DDRMPHY 3 + +struct uniphier_ddrmphy_param { + unsigned int soc_id; + unsigned int nr_phy; + struct { + resource_size_t base; + unsigned int nr_zq; + unsigned int nr_dx; + } phy[UNIPHIER_MAX_NR_DDRMPHY]; +}; + +static const struct uniphier_ddrmphy_param uniphier_ddrmphy_param[] = { + { + .soc_id = UNIPHIER_PXS2_ID, + .nr_phy = 3, + .phy = { + { .base = 0x5b830000, .nr_zq = 3, .nr_dx = 4, }, + { .base = 0x5ba30000, .nr_zq = 3, .nr_dx = 4, }, + { .base = 0x5bc30000, .nr_zq = 2, .nr_dx = 2, }, + }, + }, + { + .soc_id = UNIPHIER_LD6B_ID, + .nr_phy = 3, + .phy = { + { .base = 0x5b830000, .nr_zq = 3, .nr_dx = 4, }, + { .base = 0x5ba30000, .nr_zq = 3, .nr_dx = 4, }, + { .base = 0x5bc30000, .nr_zq = 2, .nr_dx = 2, }, + }, + }, +}; +UNIPHIER_DEFINE_SOCDATA_FUNC(uniphier_get_ddrmphy_param, uniphier_ddrmphy_param) static void print_bdl(void __iomem *reg, int n) { @@ -47,106 +66,107 @@ static void print_bdl(void __iomem *reg, int n) printf(FS PRINTF_FORMAT, (val >> i * 8) & 0x1f); } -static void dump_loop(void (*callback)(void __iomem *)) +static void dump_loop(const struct uniphier_ddrmphy_param *param, + void (*callback)(void __iomem *)) { - int ch, dx, nr_ch, nr_dx; - void __iomem *dx_base; - - nr_ch = get_nr_ch(); + void __iomem *phy_base, *dx_base; + int phy, dx; - for (ch = 0; ch < nr_ch; ch++) { - dx_base = get_phy_base(ch) + DMPHY_DX_BASE; - nr_dx = get_nr_datx8(ch); + for (phy = 0; phy < param->nr_phy; phy++) { + phy_base = ioremap(param->phy[phy].base, SZ_4K); + dx_base = phy_base + MPHY_DX_BASE; - for (dx = 0; dx < nr_dx; dx++) { - printf("CH%dDX%d:", ch, dx); + for (dx = 0; dx < param->phy[phy].nr_dx; dx++) { + printf("PHY%dDX%d:", phy, dx); (*callback)(dx_base); - dx_base += DMPHY_DX_STRIDE; + dx_base += MPHY_DX_STRIDE; printf("\n"); } + + iounmap(phy_base); } } -static void zq_dump(void) +static void zq_dump(const struct uniphier_ddrmphy_param *param) { - int ch, zq, nr_ch, nr_zq, i; - void __iomem *zq_base; - u32 dr, pr; + void __iomem *phy_base, *zq_base; + u32 val; + int phy, zq, i; printf("\n--- Impedance Data ---\n"); - printf(" ZPD ZPU OPD OPU ZDV ODV\n"); + printf(" ZPD ZPU OPD OPU ZDV ODV\n"); - nr_ch = get_nr_ch(); + for (phy = 0; phy < param->nr_phy; phy++) { + phy_base = ioremap(param->phy[phy].base, SZ_4K); + zq_base = phy_base + MPHY_ZQ_BASE; - for (ch = 0; ch < nr_ch; ch++) { - zq_base = get_phy_base(ch) + DMPHY_ZQ_BASE; - nr_zq = 3; + for (zq = 0; zq < param->phy[phy].nr_zq; zq++) { + printf("PHY%dZQ%d:", phy, zq); - for (zq = 0; zq < nr_zq; zq++) { - printf("CH%dZQ%d:", ch, zq); - - dr = readl(zq_base + DMPHY_ZQ_DR); + val = readl(zq_base + MPHY_ZQ_DR); for (i = 0; i < 4; i++) { - printf(FS PRINTF_FORMAT, dr & 0x7f); - dr >>= 7; + printf(FS PRINTF_FORMAT, val & 0x7f); + val >>= 7; } - pr = readl(zq_base + DMPHY_ZQ_PR); + val = readl(zq_base + MPHY_ZQ_PR); for (i = 0; i < 2; i++) { - printf(FS PRINTF_FORMAT, pr & 0xf); - pr >>= 4; + printf(FS PRINTF_FORMAT, val & 0xf); + val >>= 4; } - zq_base += DMPHY_ZQ_STRIDE; + zq_base += MPHY_ZQ_STRIDE; printf("\n"); } + + iounmap(phy_base); } } static void __wbdl_dump(void __iomem *dx_base) { - print_bdl(dx_base + DMPHY_DX_BDLR0, 4); - print_bdl(dx_base + DMPHY_DX_BDLR1, 4); - print_bdl(dx_base + DMPHY_DX_BDLR2, 2); + print_bdl(dx_base + MPHY_DX_BDLR0, 4); + print_bdl(dx_base + MPHY_DX_BDLR1, 4); + print_bdl(dx_base + MPHY_DX_BDLR2, 2); printf(FS "(+" PRINTF_FORMAT ")", - readl(dx_base + DMPHY_DX_LCDLR1) & 0xff); + readl(dx_base + MPHY_DX_LCDLR1) & 0xff); } -static void wbdl_dump(void) +static void wbdl_dump(const struct uniphier_ddrmphy_param *param) { printf("\n--- Write Bit Delay Line ---\n"); - printf(" DQ0 DQ1 DQ2 DQ3 DQ4 DQ5 DQ6 DQ7 DM DQS (WDQD)\n"); + printf(" DQ0 DQ1 DQ2 DQ3 DQ4 DQ5 DQ6 DQ7 DM DQS (WDQD)\n"); - dump_loop(&__wbdl_dump); + dump_loop(param, &__wbdl_dump); } static void __rbdl_dump(void __iomem *dx_base) { - print_bdl(dx_base + DMPHY_DX_BDLR3, 4); - print_bdl(dx_base + DMPHY_DX_BDLR4, 4); - print_bdl(dx_base + DMPHY_DX_BDLR5, 1); + print_bdl(dx_base + MPHY_DX_BDLR3, 4); + print_bdl(dx_base + MPHY_DX_BDLR4, 4); + print_bdl(dx_base + MPHY_DX_BDLR5, 1); printf(FS "(+" PRINTF_FORMAT ")", - (readl(dx_base + DMPHY_DX_LCDLR1) >> 8) & 0xff); + (readl(dx_base + MPHY_DX_LCDLR1) >> 8) & 0xff); printf(FS "(+" PRINTF_FORMAT ")", - (readl(dx_base + DMPHY_DX_LCDLR1) >> 16) & 0xff); + (readl(dx_base + MPHY_DX_LCDLR1) >> 16) & 0xff); } -static void rbdl_dump(void) +static void rbdl_dump(const struct uniphier_ddrmphy_param *param) { printf("\n--- Read Bit Delay Line ---\n"); - printf(" DQ0 DQ1 DQ2 DQ3 DQ4 DQ5 DQ6 DQ7 DM (RDQSD) (RDQSND)\n"); + printf(" DQ0 DQ1 DQ2 DQ3 DQ4 DQ5 DQ6 DQ7 DM (RDQSD) (RDQSND)\n"); - dump_loop(&__rbdl_dump); + dump_loop(param, &__rbdl_dump); } static void __wld_dump(void __iomem *dx_base) { int rank; - u32 lcdlr0 = readl(dx_base + DMPHY_DX_LCDLR0); - u32 gtr = readl(dx_base + DMPHY_DX_GTR); + u32 lcdlr0 = readl(dx_base + MPHY_DX_LCDLR0); + u32 gtr = readl(dx_base + MPHY_DX_GTR); for (rank = 0; rank < 4; rank++) { u32 wld = (lcdlr0 >> (8 * rank)) & 0xff; /* Delay */ @@ -157,19 +177,19 @@ static void __wld_dump(void __iomem *dx_base) } } -static void wld_dump(void) +static void wld_dump(const struct uniphier_ddrmphy_param *param) { printf("\n--- Write Leveling Delay ---\n"); - printf(" Rank0 Rank1 Rank2 Rank3\n"); + printf(" Rank0 Rank1 Rank2 Rank3\n"); - dump_loop(&__wld_dump); + dump_loop(param, &__wld_dump); } static void __dqsgd_dump(void __iomem *dx_base) { int rank; - u32 lcdlr2 = readl(dx_base + DMPHY_DX_LCDLR2); - u32 gtr = readl(dx_base + DMPHY_DX_GTR); + u32 lcdlr2 = readl(dx_base + MPHY_DX_LCDLR2); + u32 gtr = readl(dx_base + MPHY_DX_GTR); for (rank = 0; rank < 4; rank++) { u32 dqsgd = (lcdlr2 >> (8 * rank)) & 0xff; /* Delay */ @@ -179,57 +199,55 @@ static void __dqsgd_dump(void __iomem *dx_base) } } -static void dqsgd_dump(void) +static void dqsgd_dump(const struct uniphier_ddrmphy_param *param) { printf("\n--- DQS Gating Delay ---\n"); - printf(" Rank0 Rank1 Rank2 Rank3\n"); + printf(" Rank0 Rank1 Rank2 Rank3\n"); - dump_loop(&__dqsgd_dump); + dump_loop(param, &__dqsgd_dump); } static void __mdl_dump(void __iomem *dx_base) { int i; - u32 mdl = readl(dx_base + DMPHY_DX_MDLR); + u32 mdl = readl(dx_base + MPHY_DX_MDLR); for (i = 0; i < 3; i++) printf(FS PRINTF_FORMAT, (mdl >> (8 * i)) & 0xff); } -static void mdl_dump(void) +static void mdl_dump(const struct uniphier_ddrmphy_param *param) { printf("\n--- Master Delay Line ---\n"); - printf(" IPRD TPRD MDLD\n"); + printf(" IPRD TPRD MDLD\n"); - dump_loop(&__mdl_dump); + dump_loop(param, &__mdl_dump); } #define REG_DUMP(x) \ - { int ofst = DMPHY_ ## x; void __iomem *reg = phy_base + ofst; \ + { int ofst = MPHY_ ## x; void __iomem *reg = phy_base + ofst; \ printf("%3d: %-10s: %p : %08x\n", \ - ofst >> DMPHY_SHIFT, #x, reg, readl(reg)); } + ofst >> MPHY_SHIFT, #x, reg, readl(reg)); } #define DX_REG_DUMP(dx, x) \ - { int ofst = DMPHY_DX_BASE + DMPHY_DX_STRIDE * (dx) + \ - DMPHY_DX_## x; \ + { int ofst = MPHY_DX_BASE + MPHY_DX_STRIDE * (dx) + \ + MPHY_DX_## x; \ void __iomem *reg = phy_base + ofst; \ printf("%3d: DX%d%-7s: %p : %08x\n", \ - ofst >> DMPHY_SHIFT, (dx), #x, reg, readl(reg)); } + ofst >> MPHY_SHIFT, (dx), #x, reg, readl(reg)); } -static void reg_dump(void) +static void reg_dump(const struct uniphier_ddrmphy_param *param) { - int ch, dx, nr_ch, nr_dx; void __iomem *phy_base; + int phy, dx; - printf("\n--- DDR PHY registers ---\n"); + printf("\n--- DDR Multi PHY registers ---\n"); - nr_ch = get_nr_ch(); + for (phy = 0; phy < param->nr_phy; phy++) { + phy_base = ioremap(param->phy[phy].base, SZ_4K); - for (ch = 0; ch < nr_ch; ch++) { - phy_base = get_phy_base(ch); - nr_dx = get_nr_datx8(ch); - - printf("== Ch%d ==\n", ch); + printf("== PHY%d (base: %08x) ==\n", phy, + ptr_to_uint(phy_base)); printf(" No: Name : Address : Data\n"); REG_DUMP(RIDR); @@ -260,50 +278,61 @@ static void reg_dump(void) REG_DUMP(MR2); REG_DUMP(MR3); - for (dx = 0; dx < nr_dx; dx++) { + for (dx = 0; dx < param->phy[phy].nr_dx; dx++) { DX_REG_DUMP(dx, GCR0); DX_REG_DUMP(dx, GCR1); DX_REG_DUMP(dx, GCR2); DX_REG_DUMP(dx, GCR3); DX_REG_DUMP(dx, GTR); } + + iounmap(phy_base); } } static int do_ddrm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - char *cmd = argv[1]; + const struct uniphier_ddrmphy_param *param; + char *cmd; + + param = uniphier_get_ddrmphy_param(); + if (!param) { + printf("unsupported SoC\n"); + return CMD_RET_FAILURE; + } if (argc == 1) cmd = "all"; + else + cmd = argv[1]; if (!strcmp(cmd, "zq") || !strcmp(cmd, "all")) - zq_dump(); + zq_dump(param); if (!strcmp(cmd, "wbdl") || !strcmp(cmd, "all")) - wbdl_dump(); + wbdl_dump(param); if (!strcmp(cmd, "rbdl") || !strcmp(cmd, "all")) - rbdl_dump(); + rbdl_dump(param); if (!strcmp(cmd, "wld") || !strcmp(cmd, "all")) - wld_dump(); + wld_dump(param); if (!strcmp(cmd, "dqsgd") || !strcmp(cmd, "all")) - dqsgd_dump(); + dqsgd_dump(param); if (!strcmp(cmd, "mdl") || !strcmp(cmd, "all")) - mdl_dump(); + mdl_dump(param); if (!strcmp(cmd, "reg") || !strcmp(cmd, "all")) - reg_dump(); + reg_dump(param); - return 0; + return CMD_RET_SUCCESS; } U_BOOT_CMD( ddrm, 2, 1, do_ddrm, - "UniPhier DDR PHY parameters dumper", + "UniPhier DDR Multi PHY parameters dumper", "- dump all of the following\n" "ddrm zq - dump Impedance Data\n" "ddrm wbdl - dump Write Bit Delay\n" diff --git a/arch/arm/mach-uniphier/dram/cmd_ddrphy.c b/arch/arm/mach-uniphier/dram/cmd_ddrphy.c index d6d9db3..a71f704 100644 --- a/arch/arm/mach-uniphier/dram/cmd_ddrphy.c +++ b/arch/arm/mach-uniphier/dram/cmd_ddrphy.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2014 Panasonic Corporation - * Copyright (C) 2015-2016 Socionext Inc. + * Copyright (C) 2015-2017 Socionext Inc. * Author: Masahiro Yamada <yamada.masahiro@socionext.com> * * SPDX-License-Identifier: GPL-2.0+ @@ -24,35 +24,53 @@ #define ptr_to_uint(p) ((unsigned int)(unsigned long)(p)) -struct phy_param { - resource_size_t base; - unsigned int nr_dx; -}; - -static const struct phy_param uniphier_ld4_phy_param[] = { - { .base = 0x5bc01000, .nr_dx = 2, }, - { .base = 0x5be01000, .nr_dx = 2, }, - { /* sentinel */ } -}; +#define UNIPHIER_MAX_NR_DDRPHY 4 -static const struct phy_param uniphier_pro4_phy_param[] = { - { .base = 0x5bc01000, .nr_dx = 2, }, - { .base = 0x5bc02000, .nr_dx = 2, }, - { .base = 0x5be01000, .nr_dx = 2, }, - { .base = 0x5be02000, .nr_dx = 2, }, - { /* sentinel */ } +struct uniphier_ddrphy_param { + unsigned int soc_id; + unsigned int nr_phy; + struct { + resource_size_t base; + unsigned int nr_dx; + } phy[UNIPHIER_MAX_NR_DDRPHY]; }; -static const struct phy_param uniphier_sld8_phy_param[] = { - { .base = 0x5bc01000, .nr_dx = 2, }, - { .base = 0x5be01000, .nr_dx = 2, }, - { /* sentinel */ } -}; - -static const struct phy_param uniphier_ld11_phy_param[] = { - { .base = 0x5bc01000, .nr_dx = 4, }, - { /* sentinel */ } +static const struct uniphier_ddrphy_param uniphier_ddrphy_param[] = { + { + .soc_id = UNIPHIER_LD4_ID, + .nr_phy = 2, + .phy = { + { .base = 0x5bc01000, .nr_dx = 2, }, + { .base = 0x5be01000, .nr_dx = 2, }, + }, + }, + { + .soc_id = UNIPHIER_PRO4_ID, + .nr_phy = 4, + .phy = { + { .base = 0x5bc01000, .nr_dx = 2, }, + { .base = 0x5bc02000, .nr_dx = 2, }, + { .base = 0x5be01000, .nr_dx = 2, }, + { .base = 0x5be02000, .nr_dx = 2, }, + }, + }, + { + .soc_id = UNIPHIER_SLD8_ID, + .nr_phy = 2, + .phy = { + { .base = 0x5bc01000, .nr_dx = 2, }, + { .base = 0x5be01000, .nr_dx = 2, }, + }, + }, + { + .soc_id = UNIPHIER_LD11_ID, + .nr_phy = 1, + .phy = { + { .base = 0x5bc01000, .nr_dx = 4, }, + }, + }, }; +UNIPHIER_DEFINE_SOCDATA_FUNC(uniphier_get_ddrphy_param, uniphier_ddrphy_param) static void print_bdl(void __iomem *reg, int n) { @@ -63,18 +81,18 @@ static void print_bdl(void __iomem *reg, int n) printf(FS PRINTF_FORMAT, (val >> i * 6) & 0x3f); } -static void dump_loop(const struct phy_param *phy_param, +static void dump_loop(const struct uniphier_ddrphy_param *param, void (*callback)(void __iomem *)) { void __iomem *phy_base, *dx_base; - int p, dx; + int phy, dx; - for (p = 0; phy_param->base; phy_param++, p++) { - phy_base = ioremap(phy_param->base, SZ_4K); + for (phy = 0; phy < param->nr_phy; phy++) { + phy_base = ioremap(param->phy[phy].base, SZ_4K); dx_base = phy_base + PHY_DX_BASE; - for (dx = 0; dx < phy_param->nr_dx; dx++) { - printf("PHY%dDX%d:", p, dx); + for (dx = 0; dx < param->phy[phy].nr_dx; dx++) { + printf("PHY%dDX%d:", phy, dx); (*callback)(dx_base); dx_base += PHY_DX_STRIDE; printf("\n"); @@ -93,12 +111,12 @@ static void __wbdl_dump(void __iomem *dx_base) readl(dx_base + PHY_DX_LCDLR1) & 0xff); } -static void wbdl_dump(const struct phy_param *phy_param) +static void wbdl_dump(const struct uniphier_ddrphy_param *param) { printf("\n--- Write Bit Delay Line ---\n"); printf(" DQ0 DQ1 DQ2 DQ3 DQ4 DQ5 DQ6 DQ7 DM DQS (WDQD)\n"); - dump_loop(phy_param, &__wbdl_dump); + dump_loop(param, &__wbdl_dump); } static void __rbdl_dump(void __iomem *dx_base) @@ -110,12 +128,12 @@ static void __rbdl_dump(void __iomem *dx_base) (readl(dx_base + PHY_DX_LCDLR1) >> 8) & 0xff); } -static void rbdl_dump(const struct phy_param *phy_param) +static void rbdl_dump(const struct uniphier_ddrphy_param *param) { printf("\n--- Read Bit Delay Line ---\n"); printf(" DQ0 DQ1 DQ2 DQ3 DQ4 DQ5 DQ6 DQ7 DM (RDQSD)\n"); - dump_loop(phy_param, &__rbdl_dump); + dump_loop(param, &__rbdl_dump); } static void __wld_dump(void __iomem *dx_base) @@ -133,12 +151,12 @@ static void __wld_dump(void __iomem *dx_base) } } -static void wld_dump(const struct phy_param *phy_param) +static void wld_dump(const struct uniphier_ddrphy_param *param) { printf("\n--- Write Leveling Delay ---\n"); - printf(" Rank0 Rank1 Rank2 Rank3\n"); + printf(" Rank0 Rank1 Rank2 Rank3\n"); - dump_loop(phy_param, &__wld_dump); + dump_loop(param, &__wld_dump); } static void __dqsgd_dump(void __iomem *dx_base) @@ -155,28 +173,29 @@ static void __dqsgd_dump(void __iomem *dx_base) } } -static void dqsgd_dump(const struct phy_param *phy_param) +static void dqsgd_dump(const struct uniphier_ddrphy_param *param) { printf("\n--- DQS Gating Delay ---\n"); - printf(" Rank0 Rank1 Rank2 Rank3\n"); + printf(" Rank0 Rank1 Rank2 Rank3\n"); - dump_loop(phy_param, &__dqsgd_dump); + dump_loop(param, &__dqsgd_dump); } static void __mdl_dump(void __iomem *dx_base) { int i; u32 mdl = readl(dx_base + PHY_DX_MDLR); + for (i = 0; i < 3; i++) printf(FS PRINTF_FORMAT, (mdl >> (8 * i)) & 0xff); } -static void mdl_dump(const struct phy_param *phy_param) +static void mdl_dump(const struct uniphier_ddrphy_param *param) { printf("\n--- Master Delay Line ---\n"); printf(" IPRD TPRD MDLD\n"); - dump_loop(phy_param, &__mdl_dump); + dump_loop(param, &__mdl_dump); } #define REG_DUMP(x) \ @@ -193,17 +212,18 @@ static void mdl_dump(const struct phy_param *phy_param) ofst >> PHY_REG_SHIFT, (dx), #x, \ ptr_to_uint(reg), readl(reg)); } -static void reg_dump(const struct phy_param *phy_param) +static void reg_dump(const struct uniphier_ddrphy_param *param) { void __iomem *phy_base; - int p, dx; + int phy, dx; printf("\n--- DDR PHY registers ---\n"); - for (p = 0; phy_param->base; phy_param++, p++) { - phy_base = ioremap(phy_param->base, SZ_4K); + for (phy = 0; phy < param->nr_phy; phy++) { + phy_base = ioremap(param->phy[phy].base, SZ_4K); - printf("== PHY%d (base: %08x) ==\n", p, ptr_to_uint(phy_base)); + printf("== PHY%d (base: %08x) ==\n", + phy, ptr_to_uint(phy_base)); printf(" No: Name : Address : Data\n"); REG_DUMP(RIDR); @@ -231,7 +251,7 @@ static void reg_dump(const struct phy_param *phy_param) REG_DUMP(MR2); REG_DUMP(MR3); - for (dx = 0; dx < phy_param->nr_dx; dx++) { + for (dx = 0; dx < param->phy[phy].nr_dx; dx++) { DX_REG_DUMP(dx, GCR); DX_REG_DUMP(dx, GTR); } @@ -242,47 +262,37 @@ static void reg_dump(const struct phy_param *phy_param) static int do_ddr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - char *cmd = argv[1]; - const struct phy_param *phy_param; - - switch (uniphier_get_soc_id()) { - case UNIPHIER_LD4_ID: - phy_param = uniphier_ld4_phy_param; - break; - case UNIPHIER_PRO4_ID: - phy_param = uniphier_pro4_phy_param; - break; - case UNIPHIER_SLD8_ID: - phy_param = uniphier_sld8_phy_param; - break; - case UNIPHIER_LD11_ID: - phy_param = uniphier_ld11_phy_param; - break; - default: + const struct uniphier_ddrphy_param *param; + char *cmd; + + param = uniphier_get_ddrphy_param(); + if (!param) { printf("unsupported SoC\n"); return CMD_RET_FAILURE; } if (argc == 1) cmd = "all"; + else + cmd = argv[1]; if (!strcmp(cmd, "wbdl") || !strcmp(cmd, "all")) - wbdl_dump(phy_param); + wbdl_dump(param); if (!strcmp(cmd, "rbdl") || !strcmp(cmd, "all")) - rbdl_dump(phy_param); + rbdl_dump(param); if (!strcmp(cmd, "wld") || !strcmp(cmd, "all")) - wld_dump(phy_param); + wld_dump(param); if (!strcmp(cmd, "dqsgd") || !strcmp(cmd, "all")) - dqsgd_dump(phy_param); + dqsgd_dump(param); if (!strcmp(cmd, "mdl") || !strcmp(cmd, "all")) - mdl_dump(phy_param); + mdl_dump(param); if (!strcmp(cmd, "reg") || !strcmp(cmd, "all")) - reg_dump(phy_param); + reg_dump(param); return CMD_RET_SUCCESS; } diff --git a/arch/arm/mach-uniphier/dram/ddrmphy-regs.h b/arch/arm/mach-uniphier/dram/ddrmphy-regs.h index 569504d..e13ccf8 100644 --- a/arch/arm/mach-uniphier/dram/ddrmphy-regs.h +++ b/arch/arm/mach-uniphier/dram/ddrmphy-regs.h @@ -1,146 +1,146 @@ /* * UniPhier DDR MultiPHY registers * - * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * Copyright (C) 2015-2017 Socionext Inc. * * SPDX-License-Identifier: GPL-2.0+ */ -#ifndef ARCH_DDRMPHY_REGS_H -#define ARCH_DDRMPHY_REGS_H +#ifndef UNIPHIER_DDRMPHY_REGS_H +#define UNIPHIER_DDRMPHY_REGS_H #include <linux/bitops.h> -#define DMPHY_SHIFT 2 +#define MPHY_SHIFT 2 -#define DMPHY_RIDR (0x000 << DMPHY_SHIFT) -#define DMPHY_PIR (0x001 << DMPHY_SHIFT) -#define DMPHY_PIR_INIT BIT(0) /* Initialization Trigger */ -#define DMPHY_PIR_ZCAL BIT(1) /* Impedance Calibration */ -#define DMPHY_PIR_PLLINIT BIT(4) /* PLL Initialization */ -#define DMPHY_PIR_DCAL BIT(5) /* DDL Calibration */ -#define DMPHY_PIR_PHYRST BIT(6) /* PHY Reset */ -#define DMPHY_PIR_DRAMRST BIT(7) /* DRAM Reset */ -#define DMPHY_PIR_DRAMINIT BIT(8) /* DRAM Initialization */ -#define DMPHY_PIR_WL BIT(9) /* Write Leveling */ -#define DMPHY_PIR_QSGATE BIT(10) /* Read DQS Gate Training */ -#define DMPHY_PIR_WLADJ BIT(11) /* Write Leveling Adjust */ -#define DMPHY_PIR_RDDSKW BIT(12) /* Read Data Bit Deskew */ -#define DMPHY_PIR_WRDSKW BIT(13) /* Write Data Bit Deskew */ -#define DMPHY_PIR_RDEYE BIT(14) /* Read Data Eye Training */ -#define DMPHY_PIR_WREYE BIT(15) /* Write Data Eye Training */ -#define DMPHY_PIR_ZCALBYP BIT(30) /* Impedance Calib Bypass */ -#define DMPHY_PIR_INITBYP BIT(31) /* Initialization Bypass */ -#define DMPHY_PGCR0 (0x002 << DMPHY_SHIFT) -#define DMPHY_PGCR0_PHYFRST BIT(26) /* PHY FIFO Reset */ -#define DMPHY_PGCR1 (0x003 << DMPHY_SHIFT) -#define DMPHY_PGCR1_INHVT BIT(26) /* VT Calculation Inhibit */ -#define DMPHY_PGCR2 (0x004 << DMPHY_SHIFT) -#define DMPHY_PGCR2_DUALCHN BIT(28) /* Dual Channel Configuration*/ -#define DMPHY_PGCR2_ACPDDC BIT(29) /* AC Power-Down with Dual Ch*/ -#define DMPHY_PGCR3 (0x005 << DMPHY_SHIFT) -#define DMPHY_PGSR0 (0x006 << DMPHY_SHIFT) -#define DMPHY_PGSR0_IDONE BIT(0) /* Initialization Done */ -#define DMPHY_PGSR0_PLDONE BIT(1) /* PLL Lock Done */ -#define DMPHY_PGSR0_DCDONE BIT(2) /* DDL Calibration Done */ -#define DMPHY_PGSR0_ZCDONE BIT(3) /* Impedance Calibration Done */ -#define DMPHY_PGSR0_DIDONE BIT(4) /* DRAM Initialization Done */ -#define DMPHY_PGSR0_WLDONE BIT(5) /* Write Leveling Done */ -#define DMPHY_PGSR0_QSGDONE BIT(6) /* DQS Gate Training Done */ -#define DMPHY_PGSR0_WLADONE BIT(7) /* Write Leveling Adjust Done */ -#define DMPHY_PGSR0_RDDONE BIT(8) /* Read Bit Deskew Done */ -#define DMPHY_PGSR0_WDDONE BIT(9) /* Write Bit Deskew Done */ -#define DMPHY_PGSR0_REDONE BIT(10) /* Read Eye Training Done */ -#define DMPHY_PGSR0_WEDONE BIT(11) /* Write Eye Training Done */ -#define DMPHY_PGSR0_ZCERR BIT(20) /* Impedance Calib Error */ -#define DMPHY_PGSR0_WLERR BIT(21) /* Write Leveling Error */ -#define DMPHY_PGSR0_QSGERR BIT(22) /* DQS Gate Training Error */ -#define DMPHY_PGSR0_WLAERR BIT(23) /* Write Leveling Adj Error */ -#define DMPHY_PGSR0_RDERR BIT(24) /* Read Bit Deskew Error */ -#define DMPHY_PGSR0_WDERR BIT(25) /* Write Bit Deskew Error */ -#define DMPHY_PGSR0_REERR BIT(26) /* Read Eye Training Error */ -#define DMPHY_PGSR0_WEERR BIT(27) /* Write Eye Training Error */ -#define DMPHY_PGSR1 (0x007 << DMPHY_SHIFT) -#define DMPHY_PGSR1_VTSTOP BIT(30) /* VT Stop */ -#define DMPHY_PLLCR (0x008 << DMPHY_SHIFT) -#define DMPHY_PTR0 (0x009 << DMPHY_SHIFT) -#define DMPHY_PTR1 (0x00A << DMPHY_SHIFT) -#define DMPHY_PTR2 (0x00B << DMPHY_SHIFT) -#define DMPHY_PTR3 (0x00C << DMPHY_SHIFT) -#define DMPHY_PTR4 (0x00D << DMPHY_SHIFT) -#define DMPHY_ACMDLR (0x00E << DMPHY_SHIFT) -#define DMPHY_ACLCDLR (0x00F << DMPHY_SHIFT) -#define DMPHY_ACBDLR0 (0x010 << DMPHY_SHIFT) -#define DMPHY_ACBDLR1 (0x011 << DMPHY_SHIFT) -#define DMPHY_ACBDLR2 (0x012 << DMPHY_SHIFT) -#define DMPHY_ACBDLR3 (0x013 << DMPHY_SHIFT) -#define DMPHY_ACBDLR4 (0x014 << DMPHY_SHIFT) -#define DMPHY_ACBDLR5 (0x015 << DMPHY_SHIFT) -#define DMPHY_ACBDLR6 (0x016 << DMPHY_SHIFT) -#define DMPHY_ACBDLR7 (0x017 << DMPHY_SHIFT) -#define DMPHY_ACBDLR8 (0x018 << DMPHY_SHIFT) -#define DMPHY_ACBDLR9 (0x019 << DMPHY_SHIFT) -#define DMPHY_ACIOCR0 (0x01A << DMPHY_SHIFT) -#define DMPHY_ACIOCR1 (0x01B << DMPHY_SHIFT) -#define DMPHY_ACIOCR2 (0x01C << DMPHY_SHIFT) -#define DMPHY_ACIOCR3 (0x01D << DMPHY_SHIFT) -#define DMPHY_ACIOCR4 (0x01E << DMPHY_SHIFT) -#define DMPHY_ACIOCR5 (0x01F << DMPHY_SHIFT) -#define DMPHY_DXCCR (0x020 << DMPHY_SHIFT) -#define DMPHY_DSGCR (0x021 << DMPHY_SHIFT) -#define DMPHY_DCR (0x022 << DMPHY_SHIFT) -#define DMPHY_DTPR0 (0x023 << DMPHY_SHIFT) -#define DMPHY_DTPR1 (0x024 << DMPHY_SHIFT) -#define DMPHY_DTPR2 (0x025 << DMPHY_SHIFT) -#define DMPHY_DTPR3 (0x026 << DMPHY_SHIFT) -#define DMPHY_MR0 (0x027 << DMPHY_SHIFT) -#define DMPHY_MR1 (0x028 << DMPHY_SHIFT) -#define DMPHY_MR2 (0x029 << DMPHY_SHIFT) -#define DMPHY_MR3 (0x02A << DMPHY_SHIFT) -#define DMPHY_ODTCR (0x02B << DMPHY_SHIFT) -#define DMPHY_DTCR (0x02C << DMPHY_SHIFT) -#define DMPHY_DTCR_RANKEN_SHIFT 24 /* Rank Enable */ -#define DMPHY_DTCR_RANKEN_MASK (0xf << (DMPHY_DTCR_RANKEN_SHIFT)) -#define DMPHY_DTAR0 (0x02D << DMPHY_SHIFT) -#define DMPHY_DTAR1 (0x02E << DMPHY_SHIFT) -#define DMPHY_DTAR2 (0x02F << DMPHY_SHIFT) -#define DMPHY_DTAR3 (0x030 << DMPHY_SHIFT) -#define DMPHY_DTDR0 (0x031 << DMPHY_SHIFT) -#define DMPHY_DTDR1 (0x032 << DMPHY_SHIFT) -#define DMPHY_DTEDR0 (0x033 << DMPHY_SHIFT) -#define DMPHY_DTEDR1 (0x034 << DMPHY_SHIFT) -#define DMPHY_ZQCR (0x090 << DMPHY_SHIFT) -#define DMPHY_ZQCR_AVGEN BIT(16) /* Average Algorithm */ -#define DMPHY_ZQCR_FORCE_ZCAL_VT_UPDATE BIT(27) /* force VT update */ +#define MPHY_RIDR (0x000 << MPHY_SHIFT) +#define MPHY_PIR (0x001 << MPHY_SHIFT) +#define MPHY_PIR_INIT BIT(0) /* Initialization Trigger */ +#define MPHY_PIR_ZCAL BIT(1) /* Impedance Calibration */ +#define MPHY_PIR_PLLINIT BIT(4) /* PLL Initialization */ +#define MPHY_PIR_DCAL BIT(5) /* DDL Calibration */ +#define MPHY_PIR_PHYRST BIT(6) /* PHY Reset */ +#define MPHY_PIR_DRAMRST BIT(7) /* DRAM Reset */ +#define MPHY_PIR_DRAMINIT BIT(8) /* DRAM Initialization */ +#define MPHY_PIR_WL BIT(9) /* Write Leveling */ +#define MPHY_PIR_QSGATE BIT(10) /* Read DQS Gate Training */ +#define MPHY_PIR_WLADJ BIT(11) /* Write Leveling Adjust */ +#define MPHY_PIR_RDDSKW BIT(12) /* Read Data Bit Deskew */ +#define MPHY_PIR_WRDSKW BIT(13) /* Write Data Bit Deskew */ +#define MPHY_PIR_RDEYE BIT(14) /* Read Data Eye Training */ +#define MPHY_PIR_WREYE BIT(15) /* Write Data Eye Training */ +#define MPHY_PIR_ZCALBYP BIT(30) /* Impedance Calib Bypass */ +#define MPHY_PIR_INITBYP BIT(31) /* Initialization Bypass */ +#define MPHY_PGCR0 (0x002 << MPHY_SHIFT) +#define MPHY_PGCR0_PHYFRST BIT(26) /* PHY FIFO Reset */ +#define MPHY_PGCR1 (0x003 << MPHY_SHIFT) +#define MPHY_PGCR1_INHVT BIT(26) /* VT Calculation Inhibit */ +#define MPHY_PGCR2 (0x004 << MPHY_SHIFT) +#define MPHY_PGCR2_DUALCHN BIT(28) /* Dual Channel Configuration*/ +#define MPHY_PGCR2_ACPDDC BIT(29) /* AC Power-Down with Dual Ch*/ +#define MPHY_PGCR3 (0x005 << MPHY_SHIFT) +#define MPHY_PGSR0 (0x006 << MPHY_SHIFT) +#define MPHY_PGSR0_IDONE BIT(0) /* Initialization Done */ +#define MPHY_PGSR0_PLDONE BIT(1) /* PLL Lock Done */ +#define MPHY_PGSR0_DCDONE BIT(2) /* DDL Calibration Done */ +#define MPHY_PGSR0_ZCDONE BIT(3) /* Impedance Calibration Done */ +#define MPHY_PGSR0_DIDONE BIT(4) /* DRAM Initialization Done */ +#define MPHY_PGSR0_WLDONE BIT(5) /* Write Leveling Done */ +#define MPHY_PGSR0_QSGDONE BIT(6) /* DQS Gate Training Done */ +#define MPHY_PGSR0_WLADONE BIT(7) /* Write Leveling Adjust Done */ +#define MPHY_PGSR0_RDDONE BIT(8) /* Read Bit Deskew Done */ +#define MPHY_PGSR0_WDDONE BIT(9) /* Write Bit Deskew Done */ +#define MPHY_PGSR0_REDONE BIT(10) /* Read Eye Training Done */ +#define MPHY_PGSR0_WEDONE BIT(11) /* Write Eye Training Done */ +#define MPHY_PGSR0_ZCERR BIT(20) /* Impedance Calib Error */ +#define MPHY_PGSR0_WLERR BIT(21) /* Write Leveling Error */ +#define MPHY_PGSR0_QSGERR BIT(22) /* DQS Gate Training Error */ +#define MPHY_PGSR0_WLAERR BIT(23) /* Write Leveling Adj Error */ +#define MPHY_PGSR0_RDERR BIT(24) /* Read Bit Deskew Error */ +#define MPHY_PGSR0_WDERR BIT(25) /* Write Bit Deskew Error */ +#define MPHY_PGSR0_REERR BIT(26) /* Read Eye Training Error */ +#define MPHY_PGSR0_WEERR BIT(27) /* Write Eye Training Error */ +#define MPHY_PGSR1 (0x007 << MPHY_SHIFT) +#define MPHY_PGSR1_VTSTOP BIT(30) /* VT Stop */ +#define MPHY_PLLCR (0x008 << MPHY_SHIFT) +#define MPHY_PTR0 (0x009 << MPHY_SHIFT) +#define MPHY_PTR1 (0x00A << MPHY_SHIFT) +#define MPHY_PTR2 (0x00B << MPHY_SHIFT) +#define MPHY_PTR3 (0x00C << MPHY_SHIFT) +#define MPHY_PTR4 (0x00D << MPHY_SHIFT) +#define MPHY_ACMDLR (0x00E << MPHY_SHIFT) +#define MPHY_ACLCDLR (0x00F << MPHY_SHIFT) +#define MPHY_ACBDLR0 (0x010 << MPHY_SHIFT) +#define MPHY_ACBDLR1 (0x011 << MPHY_SHIFT) +#define MPHY_ACBDLR2 (0x012 << MPHY_SHIFT) +#define MPHY_ACBDLR3 (0x013 << MPHY_SHIFT) +#define MPHY_ACBDLR4 (0x014 << MPHY_SHIFT) +#define MPHY_ACBDLR5 (0x015 << MPHY_SHIFT) +#define MPHY_ACBDLR6 (0x016 << MPHY_SHIFT) +#define MPHY_ACBDLR7 (0x017 << MPHY_SHIFT) +#define MPHY_ACBDLR8 (0x018 << MPHY_SHIFT) +#define MPHY_ACBDLR9 (0x019 << MPHY_SHIFT) +#define MPHY_ACIOCR0 (0x01A << MPHY_SHIFT) +#define MPHY_ACIOCR1 (0x01B << MPHY_SHIFT) +#define MPHY_ACIOCR2 (0x01C << MPHY_SHIFT) +#define MPHY_ACIOCR3 (0x01D << MPHY_SHIFT) +#define MPHY_ACIOCR4 (0x01E << MPHY_SHIFT) +#define MPHY_ACIOCR5 (0x01F << MPHY_SHIFT) +#define MPHY_DXCCR (0x020 << MPHY_SHIFT) +#define MPHY_DSGCR (0x021 << MPHY_SHIFT) +#define MPHY_DCR (0x022 << MPHY_SHIFT) +#define MPHY_DTPR0 (0x023 << MPHY_SHIFT) +#define MPHY_DTPR1 (0x024 << MPHY_SHIFT) +#define MPHY_DTPR2 (0x025 << MPHY_SHIFT) +#define MPHY_DTPR3 (0x026 << MPHY_SHIFT) +#define MPHY_MR0 (0x027 << MPHY_SHIFT) +#define MPHY_MR1 (0x028 << MPHY_SHIFT) +#define MPHY_MR2 (0x029 << MPHY_SHIFT) +#define MPHY_MR3 (0x02A << MPHY_SHIFT) +#define MPHY_ODTCR (0x02B << MPHY_SHIFT) +#define MPHY_DTCR (0x02C << MPHY_SHIFT) +#define MPHY_DTCR_RANKEN_SHIFT 24 /* Rank Enable */ +#define MPHY_DTCR_RANKEN_MASK (0xf << (MPHY_DTCR_RANKEN_SHIFT)) +#define MPHY_DTAR0 (0x02D << MPHY_SHIFT) +#define MPHY_DTAR1 (0x02E << MPHY_SHIFT) +#define MPHY_DTAR2 (0x02F << MPHY_SHIFT) +#define MPHY_DTAR3 (0x030 << MPHY_SHIFT) +#define MPHY_DTDR0 (0x031 << MPHY_SHIFT) +#define MPHY_DTDR1 (0x032 << MPHY_SHIFT) +#define MPHY_DTEDR0 (0x033 << MPHY_SHIFT) +#define MPHY_DTEDR1 (0x034 << MPHY_SHIFT) +#define MPHY_ZQCR (0x090 << MPHY_SHIFT) +#define MPHY_ZQCR_AVGEN BIT(16) /* Average Algorithm */ +#define MPHY_ZQCR_FORCE_ZCAL_VT_UPDATE BIT(27) /* force VT update */ /* ZQ */ -#define DMPHY_ZQ_BASE (0x091 << DMPHY_SHIFT) -#define DMPHY_ZQ_STRIDE (0x004 << DMPHY_SHIFT) -#define DMPHY_ZQ_PR (0x000 << DMPHY_SHIFT) -#define DMPHY_ZQ_DR (0x001 << DMPHY_SHIFT) -#define DMPHY_ZQ_SR (0x002 << DMPHY_SHIFT) +#define MPHY_ZQ_BASE (0x091 << MPHY_SHIFT) +#define MPHY_ZQ_STRIDE (0x004 << MPHY_SHIFT) +#define MPHY_ZQ_PR (0x000 << MPHY_SHIFT) +#define MPHY_ZQ_DR (0x001 << MPHY_SHIFT) +#define MPHY_ZQ_SR (0x002 << MPHY_SHIFT) /* DATX8 */ -#define DMPHY_DX_BASE (0x0A0 << DMPHY_SHIFT) -#define DMPHY_DX_STRIDE (0x020 << DMPHY_SHIFT) -#define DMPHY_DX_GCR0 (0x000 << DMPHY_SHIFT) -#define DMPHY_DX_GCR0_WLRKEN_SHIFT 26 /* Write Level Rank Enable */ -#define DMPHY_DX_GCR0_WLRKEN_MASK (0xf << (DMPHY_DX_GCR0_WLRKEN_SHIFT)) -#define DMPHY_DX_GCR1 (0x001 << DMPHY_SHIFT) -#define DMPHY_DX_GCR2 (0x002 << DMPHY_SHIFT) -#define DMPHY_DX_GCR3 (0x003 << DMPHY_SHIFT) -#define DMPHY_DX_GSR0 (0x004 << DMPHY_SHIFT) -#define DMPHY_DX_GSR1 (0x005 << DMPHY_SHIFT) -#define DMPHY_DX_GSR2 (0x006 << DMPHY_SHIFT) -#define DMPHY_DX_BDLR0 (0x007 << DMPHY_SHIFT) -#define DMPHY_DX_BDLR1 (0x008 << DMPHY_SHIFT) -#define DMPHY_DX_BDLR2 (0x009 << DMPHY_SHIFT) -#define DMPHY_DX_BDLR3 (0x00A << DMPHY_SHIFT) -#define DMPHY_DX_BDLR4 (0x00B << DMPHY_SHIFT) -#define DMPHY_DX_BDLR5 (0x00C << DMPHY_SHIFT) -#define DMPHY_DX_BDLR6 (0x00D << DMPHY_SHIFT) -#define DMPHY_DX_LCDLR0 (0x00E << DMPHY_SHIFT) -#define DMPHY_DX_LCDLR1 (0x00F << DMPHY_SHIFT) -#define DMPHY_DX_LCDLR2 (0x010 << DMPHY_SHIFT) -#define DMPHY_DX_MDLR (0x011 << DMPHY_SHIFT) -#define DMPHY_DX_GTR (0x012 << DMPHY_SHIFT) +#define MPHY_DX_BASE (0x0A0 << MPHY_SHIFT) +#define MPHY_DX_STRIDE (0x020 << MPHY_SHIFT) +#define MPHY_DX_GCR0 (0x000 << MPHY_SHIFT) +#define MPHY_DX_GCR0_WLRKEN_SHIFT 26 /* Write Level Rank Enable */ +#define MPHY_DX_GCR0_WLRKEN_MASK (0xf << (MPHY_DX_GCR0_WLRKEN_SHIFT)) +#define MPHY_DX_GCR1 (0x001 << MPHY_SHIFT) +#define MPHY_DX_GCR2 (0x002 << MPHY_SHIFT) +#define MPHY_DX_GCR3 (0x003 << MPHY_SHIFT) +#define MPHY_DX_GSR0 (0x004 << MPHY_SHIFT) +#define MPHY_DX_GSR1 (0x005 << MPHY_SHIFT) +#define MPHY_DX_GSR2 (0x006 << MPHY_SHIFT) +#define MPHY_DX_BDLR0 (0x007 << MPHY_SHIFT) +#define MPHY_DX_BDLR1 (0x008 << MPHY_SHIFT) +#define MPHY_DX_BDLR2 (0x009 << MPHY_SHIFT) +#define MPHY_DX_BDLR3 (0x00A << MPHY_SHIFT) +#define MPHY_DX_BDLR4 (0x00B << MPHY_SHIFT) +#define MPHY_DX_BDLR5 (0x00C << MPHY_SHIFT) +#define MPHY_DX_BDLR6 (0x00D << MPHY_SHIFT) +#define MPHY_DX_LCDLR0 (0x00E << MPHY_SHIFT) +#define MPHY_DX_LCDLR1 (0x00F << MPHY_SHIFT) +#define MPHY_DX_LCDLR2 (0x010 << MPHY_SHIFT) +#define MPHY_DX_MDLR (0x011 << MPHY_SHIFT) +#define MPHY_DX_GTR (0x012 << MPHY_SHIFT) -#endif /* ARCH_DDRMPHY_REGS_H */ +#endif /* UNIPHIER_DDRMPHY_REGS_H */ diff --git a/arch/arm/mach-uniphier/dram/umc-ld20.c b/arch/arm/mach-uniphier/dram/umc-ld20.c index 61f62ae..157b915 100644 --- a/arch/arm/mach-uniphier/dram/umc-ld20.c +++ b/arch/arm/mach-uniphier/dram/umc-ld20.c @@ -1,7 +1,7 @@ /* - * Copyright (C) 2016 Socionext Inc. + * Copyright (C) 2016-2017 Socionext Inc. * - * based on commit 1f6feb76e7f9753f51955444e422486521f9b3a3 of Diag + * based on commit e732175d0b0dbc2a3855cb8ac791c538666b6fd4 of Diag * * SPDX-License-Identifier: GPL-2.0+ */ @@ -77,191 +77,95 @@ static const u32 ddrphy_scl_gate_timing[DRAM_CH_NR] = { 0x00000140, 0x00000180, 0x00000140 }; -static const int ddrphy_op_dq_shift_val[DRAM_BOARD_NR][DRAM_CH_NR][32] = { - { /* LD20 reference */ - { - 2, 1, 0, 1, 2, 1, 1, 1, - 2, 1, 1, 2, 1, 1, 1, 1, - 1, 2, 1, 1, 1, 2, 1, 1, - 2, 2, 0, 1, 1, 2, 2, 1, - }, - { - 1, 1, 0, 1, 2, 2, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 0, 0, 1, 1, 0, 0, - 0, 1, 1, 1, 2, 1, 2, 1, - }, - { - 2, 2, 0, 2, 1, 1, 2, 1, - 1, 1, 0, 1, 1, -1, 1, 1, - 2, 2, 2, 2, 1, 1, 1, 1, - 1, 1, 1, 0, 2, 2, 1, 2, - }, +static const short ddrphy_op_dq_shift_val_ld20[DRAM_CH_NR][32] = { + { + 2, 1, 0, 1, 2, 1, 1, 1, + 2, 1, 1, 2, 1, 1, 1, 1, + 1, 2, 1, 1, 1, 2, 1, 1, + 2, 2, 0, 1, 1, 2, 2, 1, }, - { /* LD20 TV */ - { - 2, 1, 0, 1, 2, 1, 1, 1, - 2, 1, 1, 2, 1, 1, 1, 1, - 1, 2, 1, 1, 1, 2, 1, 1, - 2, 2, 0, 1, 1, 2, 2, 1, - }, - { - 1, 1, 0, 1, 2, 2, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 0, 0, 1, 1, 0, 0, - 0, 1, 1, 1, 2, 1, 2, 1, - }, - { - 2, 2, 0, 2, 1, 1, 2, 1, - 1, 1, 0, 1, 1, -1, 1, 1, - 2, 2, 2, 2, 1, 1, 1, 1, - 1, 1, 1, 0, 2, 2, 1, 2, - }, + { + 1, 1, 0, 1, 2, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 0, 1, 1, 0, 0, + 0, 1, 1, 1, 2, 1, 2, 1, }, - { /* LD20 TV C1 */ - { - 2, 1, 0, 1, 2, 1, 1, 1, - 2, 1, 1, 2, 1, 1, 1, 1, - 1, 2, 1, 1, 1, 2, 1, 1, - 2, 2, 0, 1, 1, 2, 2, 1, - }, - { - 1, 1, 0, 1, 2, 2, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 0, 0, 1, 1, 0, 0, - 0, 1, 1, 1, 2, 1, 2, 1, - }, - { - 2, 2, 0, 2, 1, 1, 2, 1, - 1, 1, 0, 1, 1, -1, 1, 1, - 2, 2, 2, 2, 1, 1, 1, 1, - 1, 1, 1, 0, 2, 2, 1, 2, - }, + { + 2, 2, 0, 2, 1, 1, 2, 1, + 1, 1, 0, 1, 1, -1, 1, 1, + 2, 2, 2, 2, 1, 1, 1, 1, + 1, 1, 1, 0, 2, 2, 1, 2, }, - { /* LD21 reference */ - { - 1, 1, 0, 1, 1, 1, 1, 1, - 1, 0, 0, 0, 1, 1, 0, 2, - 1, 1, 0, 0, 1, 1, 1, 1, - 1, 0, 0, 0, 1, 0, 0, 1, - }, - { 1, 0, 2, 1, 1, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 0, 0, - 1, 0, 1, 0, 1, 1, 1, 0, - 1, 1, 1, 1, 0, 1, 0, 0, - }, - /* No CH2 */ +}; + +static const short ddrphy_op_dq_shift_val_ld21[DRAM_CH_NR][32] = { + { + 1, 1, 0, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 1, 1, 0, 2, + 1, 1, 0, 0, 1, 1, 1, 1, + 1, 0, 0, 0, 1, 0, 0, 1, }, - { /* LD21 TV */ - { - 1, 1, 0, 1, 1, 1, 1, 1, - 1, 0, 0, 0, 1, 1, 0, 2, - 1, 1, 0, 0, 1, 1, 1, 1, - 1, 0, 0, 0, 1, 0, 0, 1, - }, - { 1, 0, 2, 1, 1, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 0, 0, - 1, 0, 1, 0, 1, 1, 1, 0, - 1, 1, 1, 1, 0, 1, 0, 0, - }, - /* No CH2 */ + { 1, 0, 2, 1, 1, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 0, 0, + 1, 0, 1, 0, 1, 1, 1, 0, + 1, 1, 1, 1, 0, 1, 0, 0, }, + /* No CH2 */ +}; + +static const short (* const ddrphy_op_dq_shift_val[DRAM_BOARD_NR])[32] = { + ddrphy_op_dq_shift_val_ld20, /* LD20 reference */ + ddrphy_op_dq_shift_val_ld20, /* LD20 TV */ + ddrphy_op_dq_shift_val_ld20, /* LD20 TV C */ + ddrphy_op_dq_shift_val_ld21, /* LD21 reference */ + ddrphy_op_dq_shift_val_ld21, /* LD21 TV */ }; -static int ddrphy_ip_dq_shift_val[DRAM_BOARD_NR][DRAM_CH_NR][32] = { - { /* LD20 reference */ - { - 3, 3, 3, 2, 3, 2, 0, 2, - 2, 3, 3, 1, 2, 2, 2, 2, - 2, 2, 2, 2, 0, 1, 1, 1, - 2, 2, 2, 2, 3, 0, 2, 2, - }, - { - 2, 2, 1, 1, -1, 1, 1, 1, - 2, 0, 2, 2, 2, 1, 0, 2, - 2, 1, 2, 1, 0, 1, 1, 1, - 2, 2, 2, 2, 2, 2, 2, 2, - }, - { - 2, 2, 3, 2, 1, 2, 2, 2, - 2, 3, 4, 2, 3, 4, 3, 3, - 2, 2, 1, 2, 1, 1, 1, 1, - 2, 2, 2, 2, 1, 2, 2, 1, - }, +static const short ddrphy_ip_dq_shift_val_ld20[DRAM_CH_NR][32] = { + { + 3, 3, 3, 2, 3, 2, 0, 2, + 2, 3, 3, 1, 2, 2, 2, 2, + 2, 2, 2, 2, 0, 1, 1, 1, + 2, 2, 2, 2, 3, 0, 2, 2, }, - { /* LD20 TV */ - { - 3, 3, 3, 2, 3, 2, 0, 2, - 2, 3, 3, 1, 2, 2, 2, 2, - 2, 2, 2, 2, 0, 1, 1, 1, - 2, 2, 2, 2, 3, 0, 2, 2, - }, - { - 2, 2, 1, 1, -1, 1, 1, 1, - 2, 0, 2, 2, 2, 1, 0, 2, - 2, 1, 2, 1, 0, 1, 1, 1, - 2, 2, 2, 2, 2, 2, 2, 2, - }, - { - 2, 2, 3, 2, 1, 2, 2, 2, - 2, 3, 4, 2, 3, 4, 3, 3, - 2, 2, 1, 2, 1, 1, 1, 1, - 2, 2, 2, 2, 1, 2, 2, 1, - }, + { + 2, 2, 1, 1, -1, 1, 1, 1, + 2, 0, 2, 2, 2, 1, 0, 2, + 2, 1, 2, 1, 0, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, }, - { /* LD20 TV C1 */ - { - 3, 3, 3, 2, 3, 2, 0, 2, - 2, 3, 3, 1, 2, 2, 2, 2, - 2, 2, 2, 2, 0, 1, 1, 1, - 2, 2, 2, 2, 3, 0, 2, 2, - }, - { - 2, 2, 1, 1, -1, 1, 1, 1, - 2, 0, 2, 2, 2, 1, 0, 2, - 2, 1, 2, 1, 0, 1, 1, 1, - 2, 2, 2, 2, 2, 2, 2, 2, - }, - { - 2, 2, 3, 2, 1, 2, 2, 2, - 2, 3, 4, 2, 3, 4, 3, 3, - 2, 2, 1, 2, 1, 1, 1, 1, - 2, 2, 2, 2, 1, 2, 2, 1, - }, + { + 2, 2, 3, 2, 1, 2, 2, 2, + 2, 3, 4, 2, 3, 4, 3, 3, + 2, 2, 1, 2, 1, 1, 1, 1, + 2, 2, 2, 2, 1, 2, 2, 1, }, - { /* LD21 reference */ - { - 2, 2, 2, 2, 1, 2, 2, 2, - 2, 3, 3, 2, 2, 2, 2, 2, - 2, 1, 2, 2, 1, 1, 1, 1, - 2, 2, 2, 3, 1, 2, 2, 2, - }, - { - 3, 4, 4, 1, 0, 1, 1, 1, - 1, 2, 1, 2, 2, 3, 3, 2, - 1, 0, 2, 1, 1, 0, 1, 0, - 0, 1, 0, 0, 1, 1, 0, 1, - }, - /* No CH2 */ +}; + +static const short ddrphy_ip_dq_shift_val_ld21[DRAM_CH_NR][32] = { + { + 2, 2, 2, 2, 1, 2, 2, 2, + 2, 3, 3, 2, 2, 2, 2, 2, + 2, 1, 2, 2, 1, 1, 1, 1, + 2, 2, 2, 3, 1, 2, 2, 2, }, - { /* LD21 TV */ - { - 2, 2, 2, 2, 1, 2, 2, 2, - 2, 3, 3, 2, 2, 2, 2, 2, - 2, 1, 2, 2, 1, 1, 1, 1, - 2, 2, 2, 3, 1, 2, 2, 2, - }, - { - 3, 4, 4, 1, 0, 1, 1, 1, - 1, 2, 1, 2, 2, 3, 3, 2, - 1, 0, 2, 1, 1, 0, 1, 0, - 0, 1, 0, 0, 1, 1, 0, 1, - }, - /* No CH2 */ + { + 3, 4, 4, 1, 0, 1, 1, 1, + 1, 2, 1, 2, 2, 3, 3, 2, + 1, 0, 2, 1, 1, 0, 1, 0, + 0, 1, 0, 0, 1, 1, 0, 1, }, + /* No CH2 */ +}; + +static const short (* const ddrphy_ip_dq_shift_val[DRAM_BOARD_NR])[32] = { + ddrphy_ip_dq_shift_val_ld20, /* LD20 reference */ + ddrphy_ip_dq_shift_val_ld20, /* LD20 TV */ + ddrphy_ip_dq_shift_val_ld20, /* LD20 TV C */ + ddrphy_ip_dq_shift_val_ld21, /* LD21 reference */ + ddrphy_ip_dq_shift_val_ld21, /* LD21 TV */ }; -/* DDR PHY */ static void ddrphy_select_lane(void __iomem *phy_base, unsigned int lane, unsigned int bit) { @@ -380,7 +284,7 @@ static void ddrphy_init_tail(void __iomem *phy_base, enum dram_board board, } static void ddrphy_shift_one_dq(void __iomem *phy_base, unsigned int reg, - u32 mask, u32 incr, int shift_val) + u32 mask, u32 incr, short shift_val) { u32 tmp; int val; @@ -403,7 +307,7 @@ static void ddrphy_shift_one_dq(void __iomem *phy_base, unsigned int reg, static void ddrphy_shift_dq(void __iomem *phy_base, unsigned int reg, u32 mask, u32 incr, u32 override, - const int *shift_val_array) + const short *shift_val_array) { u32 tmp; int dx, bit; diff --git a/arch/arm/mach-uniphier/dram/umc-pxs2.c b/arch/arm/mach-uniphier/dram/umc-pxs2.c index 9aeda64..05a62de 100644 --- a/arch/arm/mach-uniphier/dram/umc-pxs2.c +++ b/arch/arm/mach-uniphier/dram/umc-pxs2.c @@ -33,6 +33,7 @@ enum dram_size { DRAM_SZ_NR, }; +/* PHY */ static u32 ddrphy_pgcr2[DRAM_FREQ_NR] = {0x00FC7E5D, 0x00FC90AB}; static u32 ddrphy_ptr0[DRAM_FREQ_NR] = {0x0EA09205, 0x10C0A6C6}; static u32 ddrphy_ptr1[DRAM_FREQ_NR] = {0x0DAC041B, 0x0FA104B1}; @@ -48,23 +49,6 @@ static u32 ddrphy_mr2[DRAM_FREQ_NR] = {0x000002a0, 0x000002a8}; /* dependent on package and board design */ static u32 ddrphy_acbdlr0[DRAM_CH_NR] = {0x0000000c, 0x0000000c, 0x00000009}; -static u32 umc_cmdctla[DRAM_FREQ_NR] = {0x66DD131D, 0x77EE1722}; -/* - * The ch2 is a different generation UMC core. - * The register spec is different, unfortunately. - */ -static u32 umc_cmdctlb_ch01[DRAM_FREQ_NR] = {0x13E87C44, 0x18F88C44}; -static u32 umc_cmdctlb_ch2[DRAM_FREQ_NR] = {0x19E8DC44, 0x1EF8EC44}; -static u32 umc_spcctla[DRAM_FREQ_NR][DRAM_SZ_NR] = { - {0x004A071D, 0x0078071D}, - {0x0055081E, 0x0089081E}, -}; - -static u32 umc_spcctlb[] = {0x00FF000A, 0x00FF000B}; -/* The ch2 is different for some reason only hardware guys know... */ -static u32 umc_flowctla_ch01[] = {0x0800001E, 0x08000022}; -static u32 umc_flowctla_ch2[] = {0x0800001E, 0x0800001E}; - /* DDR multiPHY */ static inline int ddrphy_get_rank(int dx) { @@ -75,14 +59,14 @@ static void ddrphy_fifo_reset(void __iomem *phy_base) { u32 tmp; - tmp = readl(phy_base + DMPHY_PGCR0); - tmp &= ~DMPHY_PGCR0_PHYFRST; - writel(tmp, phy_base + DMPHY_PGCR0); + tmp = readl(phy_base + MPHY_PGCR0); + tmp &= ~MPHY_PGCR0_PHYFRST; + writel(tmp, phy_base + MPHY_PGCR0); udelay(1); - tmp |= DMPHY_PGCR0_PHYFRST; - writel(tmp, phy_base + DMPHY_PGCR0); + tmp |= MPHY_PGCR0_PHYFRST; + writel(tmp, phy_base + MPHY_PGCR0); udelay(1); } @@ -91,17 +75,17 @@ static void ddrphy_vt_ctrl(void __iomem *phy_base, int enable) { u32 tmp; - tmp = readl(phy_base + DMPHY_PGCR1); + tmp = readl(phy_base + MPHY_PGCR1); if (enable) - tmp &= ~DMPHY_PGCR1_INHVT; + tmp &= ~MPHY_PGCR1_INHVT; else - tmp |= DMPHY_PGCR1_INHVT; + tmp |= MPHY_PGCR1_INHVT; - writel(tmp, phy_base + DMPHY_PGCR1); + writel(tmp, phy_base + MPHY_PGCR1); if (!enable) { - while (!(readl(phy_base + DMPHY_PGSR1) & DMPHY_PGSR1_VTSTOP)) + while (!(readl(phy_base + MPHY_PGSR1) & MPHY_PGSR1_VTSTOP)) cpu_relax(); } } @@ -110,18 +94,18 @@ static void ddrphy_dqs_delay_fixup(void __iomem *phy_base, int nr_dx, int step) { int dx; u32 lcdlr1, rdqsd; - void __iomem *dx_base = phy_base + DMPHY_DX_BASE; + void __iomem *dx_base = phy_base + MPHY_DX_BASE; ddrphy_vt_ctrl(phy_base, 0); for (dx = 0; dx < nr_dx; dx++) { - lcdlr1 = readl(dx_base + DMPHY_DX_LCDLR1); + lcdlr1 = readl(dx_base + MPHY_DX_LCDLR1); rdqsd = (lcdlr1 >> 8) & 0xff; rdqsd = clamp(rdqsd + step, 0U, 0xffU); lcdlr1 = (lcdlr1 & ~(0xff << 8)) | (rdqsd << 8); - writel(lcdlr1, dx_base + DMPHY_DX_LCDLR1); - readl(dx_base + DMPHY_DX_LCDLR1); /* relax */ - dx_base += DMPHY_DX_STRIDE; + writel(lcdlr1, dx_base + MPHY_DX_LCDLR1); + readl(dx_base + MPHY_DX_LCDLR1); /* relax */ + dx_base += MPHY_DX_STRIDE; } ddrphy_vt_ctrl(phy_base, 1); @@ -129,14 +113,14 @@ static void ddrphy_dqs_delay_fixup(void __iomem *phy_base, int nr_dx, int step) static int ddrphy_get_system_latency(void __iomem *phy_base, int width) { - void __iomem *dx_base = phy_base + DMPHY_DX_BASE; + void __iomem *dx_base = phy_base + MPHY_DX_BASE; const int nr_dx = width / 8; int dx, rank; u32 gtr; int dgsl, dgsl_min = INT_MAX, dgsl_max = 0; for (dx = 0; dx < nr_dx; dx++) { - gtr = readl(dx_base + DMPHY_DX_GTR); + gtr = readl(dx_base + MPHY_DX_GTR); for (rank = 0; rank < 4; rank++) { dgsl = gtr & 0x7; /* if dgsl is zero, this rank was not trained. skip. */ @@ -146,7 +130,7 @@ static int ddrphy_get_system_latency(void __iomem *phy_base, int width) } gtr >>= 3; } - dx_base += DMPHY_DX_STRIDE; + dx_base += MPHY_DX_STRIDE; } if (dgsl_min != dgsl_max) @@ -165,86 +149,86 @@ static void ddrphy_init(void __iomem *phy_base, enum dram_freq freq, int width, nr_dx = width / 8; - writel(DMPHY_PIR_ZCALBYP, phy_base + DMPHY_PIR); + writel(MPHY_PIR_ZCALBYP, phy_base + MPHY_PIR); /* * Disable RGLVT bit (Read DQS Gating LCDL Delay VT Compensation) * to avoid read error issue. */ - writel(0x07d81e37, phy_base + DMPHY_PGCR0); - writel(0x0200c4e0, phy_base + DMPHY_PGCR1); + writel(0x07d81e37, phy_base + MPHY_PGCR0); + writel(0x0200c4e0, phy_base + MPHY_PGCR1); tmp = ddrphy_pgcr2[freq]; if (width >= 32) - tmp |= DMPHY_PGCR2_DUALCHN | DMPHY_PGCR2_ACPDDC; - writel(tmp, phy_base + DMPHY_PGCR2); - - writel(ddrphy_ptr0[freq], phy_base + DMPHY_PTR0); - writel(ddrphy_ptr1[freq], phy_base + DMPHY_PTR1); - writel(0x00083def, phy_base + DMPHY_PTR2); - writel(ddrphy_ptr3[freq], phy_base + DMPHY_PTR3); - writel(ddrphy_ptr4[freq], phy_base + DMPHY_PTR4); - - writel(ddrphy_acbdlr0[ch], phy_base + DMPHY_ACBDLR0); - - writel(0x55555555, phy_base + DMPHY_ACIOCR1); - writel(0x00000000, phy_base + DMPHY_ACIOCR2); - writel(0x55555555, phy_base + DMPHY_ACIOCR3); - writel(0x00000000, phy_base + DMPHY_ACIOCR4); - writel(0x00000055, phy_base + DMPHY_ACIOCR5); - writel(0x00181aa4, phy_base + DMPHY_DXCCR); - - writel(0x0024641e, phy_base + DMPHY_DSGCR); - writel(0x0000040b, phy_base + DMPHY_DCR); - writel(ddrphy_dtpr0[freq], phy_base + DMPHY_DTPR0); - writel(ddrphy_dtpr1[freq], phy_base + DMPHY_DTPR1); - writel(ddrphy_dtpr2[freq], phy_base + DMPHY_DTPR2); - writel(ddrphy_dtpr3[freq], phy_base + DMPHY_DTPR3); - writel(ddrphy_mr0[freq], phy_base + DMPHY_MR0); - writel(0x00000006, phy_base + DMPHY_MR1); - writel(ddrphy_mr2[freq], phy_base + DMPHY_MR2); - writel(0x00000000, phy_base + DMPHY_MR3); + tmp |= MPHY_PGCR2_DUALCHN | MPHY_PGCR2_ACPDDC; + writel(tmp, phy_base + MPHY_PGCR2); + + writel(ddrphy_ptr0[freq], phy_base + MPHY_PTR0); + writel(ddrphy_ptr1[freq], phy_base + MPHY_PTR1); + writel(0x00083def, phy_base + MPHY_PTR2); + writel(ddrphy_ptr3[freq], phy_base + MPHY_PTR3); + writel(ddrphy_ptr4[freq], phy_base + MPHY_PTR4); + + writel(ddrphy_acbdlr0[ch], phy_base + MPHY_ACBDLR0); + + writel(0x55555555, phy_base + MPHY_ACIOCR1); + writel(0x00000000, phy_base + MPHY_ACIOCR2); + writel(0x55555555, phy_base + MPHY_ACIOCR3); + writel(0x00000000, phy_base + MPHY_ACIOCR4); + writel(0x00000055, phy_base + MPHY_ACIOCR5); + writel(0x00181aa4, phy_base + MPHY_DXCCR); + + writel(0x0024641e, phy_base + MPHY_DSGCR); + writel(0x0000040b, phy_base + MPHY_DCR); + writel(ddrphy_dtpr0[freq], phy_base + MPHY_DTPR0); + writel(ddrphy_dtpr1[freq], phy_base + MPHY_DTPR1); + writel(ddrphy_dtpr2[freq], phy_base + MPHY_DTPR2); + writel(ddrphy_dtpr3[freq], phy_base + MPHY_DTPR3); + writel(ddrphy_mr0[freq], phy_base + MPHY_MR0); + writel(0x00000006, phy_base + MPHY_MR1); + writel(ddrphy_mr2[freq], phy_base + MPHY_MR2); + writel(0x00000000, phy_base + MPHY_MR3); tmp = 0; for (dx = 0; dx < nr_dx; dx++) - tmp |= BIT(DMPHY_DTCR_RANKEN_SHIFT + ddrphy_get_rank(dx)); - writel(0x90003087 | tmp, phy_base + DMPHY_DTCR); + tmp |= BIT(MPHY_DTCR_RANKEN_SHIFT + ddrphy_get_rank(dx)); + writel(0x90003087 | tmp, phy_base + MPHY_DTCR); - writel(0x00000000, phy_base + DMPHY_DTAR0); - writel(0x00000008, phy_base + DMPHY_DTAR1); - writel(0x00000010, phy_base + DMPHY_DTAR2); - writel(0x00000018, phy_base + DMPHY_DTAR3); - writel(0xdd22ee11, phy_base + DMPHY_DTDR0); - writel(0x7788bb44, phy_base + DMPHY_DTDR1); + writel(0x00000000, phy_base + MPHY_DTAR0); + writel(0x00000008, phy_base + MPHY_DTAR1); + writel(0x00000010, phy_base + MPHY_DTAR2); + writel(0x00000018, phy_base + MPHY_DTAR3); + writel(0xdd22ee11, phy_base + MPHY_DTDR0); + writel(0x7788bb44, phy_base + MPHY_DTDR1); /* impedance control settings */ - writel(0x04048900, phy_base + DMPHY_ZQCR); + writel(0x04048900, phy_base + MPHY_ZQCR); - zq_base = phy_base + DMPHY_ZQ_BASE; + zq_base = phy_base + MPHY_ZQ_BASE; for (zq = 0; zq < 4; zq++) { /* * board-dependent * PXS2: CH0ZQ0=0x5B, CH1ZQ0=0x5B, CH2ZQ0=0x59, others=0x5D */ - writel(0x0007BB5D, zq_base + DMPHY_ZQ_PR); - zq_base += DMPHY_ZQ_STRIDE; + writel(0x0007BB5D, zq_base + MPHY_ZQ_PR); + zq_base += MPHY_ZQ_STRIDE; } /* DATX8 settings */ - dx_base = phy_base + DMPHY_DX_BASE; + dx_base = phy_base + MPHY_DX_BASE; for (dx = 0; dx < 4; dx++) { - tmp = readl(dx_base + DMPHY_DX_GCR0); - tmp &= ~DMPHY_DX_GCR0_WLRKEN_MASK; - tmp |= BIT(DMPHY_DX_GCR0_WLRKEN_SHIFT + ddrphy_get_rank(dx)) & - DMPHY_DX_GCR0_WLRKEN_MASK; - writel(tmp, dx_base + DMPHY_DX_GCR0); - - writel(0x00000000, dx_base + DMPHY_DX_GCR1); - writel(0x00000000, dx_base + DMPHY_DX_GCR2); - writel(0x00000000, dx_base + DMPHY_DX_GCR3); - dx_base += DMPHY_DX_STRIDE; + tmp = readl(dx_base + MPHY_DX_GCR0); + tmp &= ~MPHY_DX_GCR0_WLRKEN_MASK; + tmp |= BIT(MPHY_DX_GCR0_WLRKEN_SHIFT + ddrphy_get_rank(dx)) & + MPHY_DX_GCR0_WLRKEN_MASK; + writel(tmp, dx_base + MPHY_DX_GCR0); + + writel(0x00000000, dx_base + MPHY_DX_GCR1); + writel(0x00000000, dx_base + MPHY_DX_GCR2); + writel(0x00000000, dx_base + MPHY_DX_GCR3); + dx_base += MPHY_DX_STRIDE; } - while (!(readl(phy_base + DMPHY_PGSR0) & DMPHY_PGSR0_IDONE)) + while (!(readl(phy_base + MPHY_PGSR0) & MPHY_PGSR0_IDONE)) cpu_relax(); ddrphy_dqs_delay_fixup(phy_base, nr_dx, -4); @@ -260,9 +244,9 @@ struct ddrphy_init_sequence { static const struct ddrphy_init_sequence impedance_calibration_sequence[] = { { "Impedance Calibration", - DMPHY_PIR_ZCAL, - DMPHY_PGSR0_ZCDONE, - DMPHY_PGSR0_ZCERR, + MPHY_PIR_ZCAL, + MPHY_PGSR0_ZCDONE, + MPHY_PGSR0_ZCERR, }, { /* sentinel */ } }; @@ -270,8 +254,8 @@ static const struct ddrphy_init_sequence impedance_calibration_sequence[] = { static const struct ddrphy_init_sequence dram_init_sequence[] = { { "DRAM Initialization", - DMPHY_PIR_DRAMRST | DMPHY_PIR_DRAMINIT, - DMPHY_PGSR0_DIDONE, + MPHY_PIR_DRAMRST | MPHY_PIR_DRAMINIT, + MPHY_PGSR0_DIDONE, 0, }, { /* sentinel */ } @@ -280,45 +264,45 @@ static const struct ddrphy_init_sequence dram_init_sequence[] = { static const struct ddrphy_init_sequence training_sequence[] = { { "Write Leveling", - DMPHY_PIR_WL, - DMPHY_PGSR0_WLDONE, - DMPHY_PGSR0_WLERR, + MPHY_PIR_WL, + MPHY_PGSR0_WLDONE, + MPHY_PGSR0_WLERR, }, { "Read DQS Gate Training", - DMPHY_PIR_QSGATE, - DMPHY_PGSR0_QSGDONE, - DMPHY_PGSR0_QSGERR, + MPHY_PIR_QSGATE, + MPHY_PGSR0_QSGDONE, + MPHY_PGSR0_QSGERR, }, { "Write Leveling Adjustment", - DMPHY_PIR_WLADJ, - DMPHY_PGSR0_WLADONE, - DMPHY_PGSR0_WLAERR, + MPHY_PIR_WLADJ, + MPHY_PGSR0_WLADONE, + MPHY_PGSR0_WLAERR, }, { "Read Bit Deskew", - DMPHY_PIR_RDDSKW, - DMPHY_PGSR0_RDDONE, - DMPHY_PGSR0_RDERR, + MPHY_PIR_RDDSKW, + MPHY_PGSR0_RDDONE, + MPHY_PGSR0_RDERR, }, { "Write Bit Deskew", - DMPHY_PIR_WRDSKW, - DMPHY_PGSR0_WDDONE, - DMPHY_PGSR0_WDERR, + MPHY_PIR_WRDSKW, + MPHY_PGSR0_WDDONE, + MPHY_PGSR0_WDERR, }, { "Read Eye Training", - DMPHY_PIR_RDEYE, - DMPHY_PGSR0_REDONE, - DMPHY_PGSR0_REERR, + MPHY_PIR_RDEYE, + MPHY_PGSR0_REDONE, + MPHY_PGSR0_REERR, }, { "Write Eye Training", - DMPHY_PIR_WREYE, - DMPHY_PGSR0_WEDONE, - DMPHY_PGSR0_WEERR, + MPHY_PIR_WREYE, + MPHY_PGSR0_WEDONE, + MPHY_PGSR0_WEERR, }, { /* sentinel */ } }; @@ -328,8 +312,8 @@ static int __ddrphy_training(void __iomem *phy_base, { const struct ddrphy_init_sequence *s; u32 pgsr0; - u32 init_flag = DMPHY_PIR_INIT; - u32 done_flag = DMPHY_PGSR0_IDONE; + u32 init_flag = MPHY_PIR_INIT; + u32 done_flag = MPHY_PGSR0_IDONE; int timeout = 50000; /* 50 msec is long enough */ #ifdef DISPLAY_ELAPSED_TIME ulong start = get_timer(0); @@ -340,7 +324,7 @@ static int __ddrphy_training(void __iomem *phy_base, done_flag |= s->done_flag; } - writel(init_flag, phy_base + DMPHY_PIR); + writel(init_flag, phy_base + MPHY_PIR); do { if (--timeout < 0) { @@ -349,7 +333,7 @@ static int __ddrphy_training(void __iomem *phy_base, return -ETIMEDOUT; } udelay(1); - pgsr0 = readl(phy_base + DMPHY_PGSR0); + pgsr0 = readl(phy_base + MPHY_PGSR0); } while ((pgsr0 & done_flag) != done_flag); for (s = seq; s->description; s++) { @@ -384,12 +368,12 @@ static int ddrphy_impedance_calibration(void __iomem *phy_base) udelay(1); /* reflect ZQ settings and enable average algorithm*/ - tmp = readl(phy_base + DMPHY_ZQCR); - tmp |= DMPHY_ZQCR_FORCE_ZCAL_VT_UPDATE; - writel(tmp, phy_base + DMPHY_ZQCR); - tmp &= ~DMPHY_ZQCR_FORCE_ZCAL_VT_UPDATE; - tmp |= DMPHY_ZQCR_AVGEN; - writel(tmp, phy_base + DMPHY_ZQCR); + tmp = readl(phy_base + MPHY_ZQCR); + tmp |= MPHY_ZQCR_FORCE_ZCAL_VT_UPDATE; + writel(tmp, phy_base + MPHY_ZQCR); + tmp &= ~MPHY_ZQCR_FORCE_ZCAL_VT_UPDATE; + tmp |= MPHY_ZQCR_AVGEN; + writel(tmp, phy_base + MPHY_ZQCR); return 0; } @@ -405,6 +389,23 @@ static int ddrphy_training(void __iomem *phy_base) } /* UMC */ +static u32 umc_cmdctla[DRAM_FREQ_NR] = {0x66DD131D, 0x77EE1722}; +/* + * The ch2 is a different generation UMC core. + * The register spec is different, unfortunately. + */ +static u32 umc_cmdctlb_ch01[DRAM_FREQ_NR] = {0x13E87C44, 0x18F88C44}; +static u32 umc_cmdctlb_ch2[DRAM_FREQ_NR] = {0x19E8DC44, 0x1EF8EC44}; +static u32 umc_spcctla[DRAM_FREQ_NR][DRAM_SZ_NR] = { + {0x004A071D, 0x0078071D}, + {0x0055081E, 0x0089081E}, +}; + +static u32 umc_spcctlb[] = {0x00FF000A, 0x00FF000B}; +/* The ch2 is different for some reason only hardware guys know... */ +static u32 umc_flowctla_ch01[] = {0x0800001E, 0x08000022}; +static u32 umc_flowctla_ch2[] = {0x0800001E, 0x0800001E}; + static void umc_set_system_latency(void __iomem *dc_base, int phy_latency) { u32 val; diff --git a/arch/arm/mach-uniphier/dram_init.c b/arch/arm/mach-uniphier/dram_init.c index 2cf5f36..881062d 100644 --- a/arch/arm/mach-uniphier/dram_init.c +++ b/arch/arm/mach-uniphier/dram_init.c @@ -1,87 +1,243 @@ /* - * Copyright (C) 2012-2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * Copyright (C) 2012-2015 Panasonic Corporation + * Copyright (C) 2015-2017 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> * * SPDX-License-Identifier: GPL-2.0+ */ #include <common.h> -#include <libfdt.h> #include <fdtdec.h> #include <linux/errno.h> +#include <linux/sizes.h> #include "init.h" +#include "sg-regs.h" #include "soc-info.h" DECLARE_GLOBAL_DATA_PTR; -static const void *get_memory_reg_prop(const void *fdt, int *lenp) +struct uniphier_memif_data { + unsigned int soc_id; + unsigned long sparse_ch1_base; + int have_ch2; +}; + +static const struct uniphier_memif_data uniphier_memif_data[] = { + { + .soc_id = UNIPHIER_SLD3_ID, + .sparse_ch1_base = 0xc0000000, + /* + * In fact, SLD3 has DRAM ch2, but the memory regions for ch1 + * and ch2 overlap, and host cannot get access to them at the + * same time. Hide the ch2 from U-Boot. + */ + }, + { + .soc_id = UNIPHIER_LD4_ID, + .sparse_ch1_base = 0xc0000000, + }, + { + .soc_id = UNIPHIER_PRO4_ID, + .sparse_ch1_base = 0xa0000000, + }, + { + .soc_id = UNIPHIER_SLD8_ID, + .sparse_ch1_base = 0xc0000000, + }, + { + .soc_id = UNIPHIER_PRO5_ID, + .sparse_ch1_base = 0xc0000000, + }, + { + .soc_id = UNIPHIER_PXS2_ID, + .sparse_ch1_base = 0xc0000000, + .have_ch2 = 1, + }, + { + .soc_id = UNIPHIER_LD6B_ID, + .sparse_ch1_base = 0xc0000000, + .have_ch2 = 1, + }, + { + .soc_id = UNIPHIER_LD11_ID, + .sparse_ch1_base = 0xc0000000, + }, + { + .soc_id = UNIPHIER_LD20_ID, + .sparse_ch1_base = 0xc0000000, + .have_ch2 = 1, + }, + { + .soc_id = UNIPHIER_PXS3_ID, + .sparse_ch1_base = 0xc0000000, + .have_ch2 = 1, + }, +}; +UNIPHIER_DEFINE_SOCDATA_FUNC(uniphier_get_memif_data, uniphier_memif_data) + +static int uniphier_memconf_decode(struct uniphier_dram_ch *dram_ch) { - int offset; + const struct uniphier_memif_data *data; + unsigned long size; + u32 val; - offset = fdt_path_offset(fdt, "/memory"); - if (offset < 0) - return NULL; + data = uniphier_get_memif_data(); + if (!data) { + pr_err("unsupported SoC\n"); + return -EINVAL; + } - return fdt_getprop(fdt, offset, "reg", lenp); -} + val = readl(SG_MEMCONF); -int dram_init(void) -{ - const void *fdt = gd->fdt_blob; - const fdt32_t *val; - int ac, sc, len; - - ac = fdt_address_cells(fdt, 0); - sc = fdt_size_cells(fdt, 0); - if (ac < 0 || sc < 1 || sc > 2) { - printf("invalid address/size cells\n"); + /* set up ch0 */ + dram_ch[0].base = CONFIG_SYS_SDRAM_BASE; + + switch (val & SG_MEMCONF_CH0_SZ_MASK) { + case SG_MEMCONF_CH0_SZ_64M: + size = SZ_64M; + break; + case SG_MEMCONF_CH0_SZ_128M: + size = SZ_128M; + break; + case SG_MEMCONF_CH0_SZ_256M: + size = SZ_256M; + break; + case SG_MEMCONF_CH0_SZ_512M: + size = SZ_512M; + break; + case SG_MEMCONF_CH0_SZ_1G: + size = SZ_1G; + break; + default: + pr_err("error: invald value is set to MEMCONF ch0 size\n"); return -EINVAL; } - val = get_memory_reg_prop(fdt, &len); - if (len / sizeof(*val) < ac + sc) + if ((val & SG_MEMCONF_CH0_NUM_MASK) == SG_MEMCONF_CH0_NUM_2) + size *= 2; + + dram_ch[0].size = size; + + /* set up ch1 */ + dram_ch[1].base = dram_ch[0].base + size; + + if (val & SG_MEMCONF_SPARSEMEM) { + if (dram_ch[1].base > data->sparse_ch1_base) { + pr_warn("Sparse mem is enabled, but ch0 and ch1 overlap\n"); + pr_warn("Only ch0 is available\n"); + dram_ch[1].base = 0; + return 0; + } + + dram_ch[1].base = data->sparse_ch1_base; + } + + switch (val & SG_MEMCONF_CH1_SZ_MASK) { + case SG_MEMCONF_CH1_SZ_64M: + size = SZ_64M; + break; + case SG_MEMCONF_CH1_SZ_128M: + size = SZ_128M; + break; + case SG_MEMCONF_CH1_SZ_256M: + size = SZ_256M; + break; + case SG_MEMCONF_CH1_SZ_512M: + size = SZ_512M; + break; + case SG_MEMCONF_CH1_SZ_1G: + size = SZ_1G; + break; + default: + pr_err("error: invald value is set to MEMCONF ch1 size\n"); return -EINVAL; + } - val += ac; + if ((val & SG_MEMCONF_CH1_NUM_MASK) == SG_MEMCONF_CH1_NUM_2) + size *= 2; - gd->ram_size = fdtdec_get_number(val, sc); + dram_ch[1].size = size; - debug("DRAM size = %08lx\n", (unsigned long)gd->ram_size); + if (!data->have_ch2) + return 0; + + /* set up ch2 */ + dram_ch[2].base = dram_ch[1].base + size; + + switch (val & SG_MEMCONF_CH2_SZ_MASK) { + case SG_MEMCONF_CH2_SZ_64M: + size = SZ_64M; + break; + case SG_MEMCONF_CH2_SZ_128M: + size = SZ_128M; + break; + case SG_MEMCONF_CH2_SZ_256M: + size = SZ_256M; + break; + case SG_MEMCONF_CH2_SZ_512M: + size = SZ_512M; + break; + case SG_MEMCONF_CH2_SZ_1G: + size = SZ_1G; + break; + default: + pr_err("error: invald value is set to MEMCONF ch2 size\n"); + return -EINVAL; + } + + if ((val & SG_MEMCONF_CH2_NUM_MASK) == SG_MEMCONF_CH2_NUM_2) + size *= 2; + + dram_ch[2].size = size; return 0; } -void dram_init_banksize(void) +int dram_init(void) { - const void *fdt = gd->fdt_blob; - const fdt32_t *val; - int ac, sc, cells, len, i; - - val = get_memory_reg_prop(fdt, &len); - if (len < 0) - return; - - ac = fdt_address_cells(fdt, 0); - sc = fdt_size_cells(fdt, 0); - if (ac < 1 || sc > 2 || sc < 1 || sc > 2) { - printf("invalid address/size cells\n"); - return; + struct uniphier_dram_ch dram_ch[UNIPHIER_MAX_NR_DRAM_CH] = {}; + int ret, i; + + gd->ram_size = 0; + + ret = uniphier_memconf_decode(dram_ch); + if (ret) + return ret; + + for (i = 0; i < ARRAY_SIZE(dram_ch); i++) { + + if (!dram_ch[i].size) + break; + + /* + * U-Boot relocates itself to the tail of the memory region, + * but it does not expect sparse memory. We use the first + * contiguous chunk here. + */ + if (i > 0 && + dram_ch[i - 1].base + dram_ch[i - 1].size < dram_ch[i].base) + break; + + gd->ram_size += dram_ch[i].size; } - cells = ac + sc; + return 0; +} - len /= sizeof(*val); +void dram_init_banksize(void) +{ + struct uniphier_dram_ch dram_ch[UNIPHIER_MAX_NR_DRAM_CH] = {}; + int i; + + uniphier_memconf_decode(dram_ch); - for (i = 0; i < CONFIG_NR_DRAM_BANKS && len >= cells; - i++, len -= cells) { - gd->bd->bi_dram[i].start = fdtdec_get_number(val, ac); - val += ac; - gd->bd->bi_dram[i].size = fdtdec_get_number(val, sc); - val += sc; + for (i = 0; i < ARRAY_SIZE(dram_ch); i++) { + if (i >= ARRAY_SIZE(gd->bd->bi_dram)) + break; - debug("DRAM bank %d: start = %08lx, size = %08lx\n", - i, (unsigned long)gd->bd->bi_dram[i].start, - (unsigned long)gd->bd->bi_dram[i].size); + gd->bd->bi_dram[i].start = dram_ch[i].base; + gd->bd->bi_dram[i].size = dram_ch[i].size; } } @@ -92,22 +248,15 @@ void dram_init_banksize(void) */ int ft_board_setup(void *fdt, bd_t *bd) { - const struct uniphier_board_data *param; unsigned long rsv_addr; const unsigned long rsv_size = 64; - int ch, ret; + int i, ret; if (uniphier_get_soc_id() != UNIPHIER_LD20_ID) return 0; - param = uniphier_get_board_param(); - if (!param) { - printf("failed to get board parameter\n"); - return -ENODEV; - } - - for (ch = 0; ch < param->dram_nr_ch; ch++) { - rsv_addr = param->dram_ch[ch].base + param->dram_ch[ch].size; + for (i = 0; i < ARRAY_SIZE(gd->bd->bi_dram); i++) { + rsv_addr = gd->bd->bi_dram[i].start + gd->bd->bi_dram[i].size; rsv_addr -= rsv_size; ret = fdt_add_mem_rsv(fdt, rsv_addr, rsv_size); diff --git a/arch/arm/mach-uniphier/init.h b/arch/arm/mach-uniphier/init.h index 3aeb5b1..453e68a 100644 --- a/arch/arm/mach-uniphier/init.h +++ b/arch/arm/mach-uniphier/init.h @@ -124,6 +124,7 @@ int uniphier_pin_init(const char *pinconfig_name); void uniphier_smp_kick_all_cpus(void); void cci500_init(int nr_slaves); +#define pr_warn(fmt, args...) printf(fmt, ##args) #define pr_err(fmt, args...) printf(fmt, ##args) #endif /* __MACH_INIT_H */ |