diff options
Diffstat (limited to 'arch/arm/mach-uniphier/dram/cmd_ddrphy.c')
| -rw-r--r-- | arch/arm/mach-uniphier/dram/cmd_ddrphy.c | 229 | 
1 files changed, 229 insertions, 0 deletions
| diff --git a/arch/arm/mach-uniphier/dram/cmd_ddrphy.c b/arch/arm/mach-uniphier/dram/cmd_ddrphy.c new file mode 100644 index 00000000000..078eb6f71b4 --- /dev/null +++ b/arch/arm/mach-uniphier/dram/cmd_ddrphy.c @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2014-2015 Masahiro Yamada <yamada.masahiro@socionext.com> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <linux/io.h> + +#include "ddrphy-regs.h" + +/* Select either decimal or hexadecimal */ +#if 1 +#define PRINTF_FORMAT "%2d" +#else +#define PRINTF_FORMAT "%02x" +#endif +/* field separator */ +#define FS "   " + +static u32 read_bdl(struct ddrphy_datx8 __iomem *dx, int index) +{ +	return (readl(&dx->bdlr[index / 5]) >> (index % 5 * 6)) & 0x3f; +} + +static void dump_loop(void (*callback)(struct ddrphy_datx8 __iomem *)) +{ +	int ch, p, dx; +	struct ddrphy __iomem *phy; + +	for (ch = 0; ch < NR_DDRCH; ch++) { +		for (p = 0; p < NR_DDRPHY_PER_CH; p++) { +			phy = (struct ddrphy __iomem *)DDRPHY_BASE(ch, p); + +			for (dx = 0; dx < NR_DATX8_PER_DDRPHY; dx++) { +				printf("CH%dP%dDX%d:", ch, p, dx); +				(*callback)(&phy->dx[dx]); +				printf("\n"); +			} +		} +	} +} + +static void __wbdl_dump(struct ddrphy_datx8 __iomem *dx) +{ +	int i; + +	for (i = 0; i < 10; i++) +		printf(FS PRINTF_FORMAT, read_bdl(dx, i)); + +	printf(FS "(+" PRINTF_FORMAT ")", readl(&dx->lcdlr[1]) & 0xff); +} + +static void wbdl_dump(void) +{ +	printf("\n--- Write Bit Delay Line ---\n"); +	printf("           DQ0  DQ1  DQ2  DQ3  DQ4  DQ5  DQ6  DQ7   DM  DQS  (WDQD)\n"); + +	dump_loop(&__wbdl_dump); +} + +static void __rbdl_dump(struct ddrphy_datx8 __iomem *dx) +{ +	int i; + +	for (i = 15; i < 24; i++) +		printf(FS PRINTF_FORMAT, read_bdl(dx, i)); + +	printf(FS "(+" PRINTF_FORMAT ")", (readl(&dx->lcdlr[1]) >> 8) & 0xff); +} + +static void rbdl_dump(void) +{ +	printf("\n--- Read Bit Delay Line ---\n"); +	printf("           DQ0  DQ1  DQ2  DQ3  DQ4  DQ5  DQ6  DQ7   DM  (RDQSD)\n"); + +	dump_loop(&__rbdl_dump); +} + +static void __wld_dump(struct ddrphy_datx8 __iomem *dx) +{ +	int rank; +	u32 lcdlr0 = readl(&dx->lcdlr[0]); +	u32 gtr = readl(&dx->gtr); + +	for (rank = 0; rank < 4; rank++) { +		u32 wld = (lcdlr0 >> (8 * rank)) & 0xff; /* Delay */ +		u32 wlsl = (gtr >> (12 + 2 * rank)) & 0x3; /* System Latency */ + +		printf(FS PRINTF_FORMAT "%sT", wld, +		       wlsl == 0 ? "-1" : wlsl == 1 ? "+0" : "+1"); +	} +} + +static void wld_dump(void) +{ +	printf("\n--- Write Leveling Delay ---\n"); +	printf("            Rank0   Rank1   Rank2   Rank3\n"); + +	dump_loop(&__wld_dump); +} + +static void __dqsgd_dump(struct ddrphy_datx8 __iomem *dx) +{ +	int rank; +	u32 lcdlr2 = readl(&dx->lcdlr[2]); +	u32 gtr = readl(&dx->gtr); + +	for (rank = 0; rank < 4; rank++) { +		u32 dqsgd = (lcdlr2 >> (8 * rank)) & 0xff; /* Delay */ +		u32 dgsl = (gtr >> (3 * rank)) & 0x7; /* System Latency */ + +		printf(FS PRINTF_FORMAT "+%dT", dqsgd, dgsl); +	} +} + +static void dqsgd_dump(void) +{ +	printf("\n--- DQS Gating Delay ---\n"); +	printf("            Rank0   Rank1   Rank2   Rank3\n"); + +	dump_loop(&__dqsgd_dump); +} + +static void __mdl_dump(struct ddrphy_datx8 __iomem *dx) +{ +	int i; +	u32 mdl = readl(&dx->mdlr); +	for (i = 0; i < 3; i++) +		printf(FS PRINTF_FORMAT, (mdl >> (8 * i)) & 0xff); +} + +static void mdl_dump(void) +{ +	printf("\n--- Master Delay Line ---\n"); +	printf("          IPRD TPRD MDLD\n"); + +	dump_loop(&__mdl_dump); +} + +#define REG_DUMP(x) \ +	{ u32 __iomem *p = &phy->x; printf("%3d: %-10s: %p : %08x\n", \ +					p - (u32 *)phy, #x, p, readl(p)); } + +static void reg_dump(void) +{ +	int ch, p; +	struct ddrphy __iomem *phy; + +	printf("\n--- DDR PHY registers ---\n"); + +	for (ch = 0; ch < NR_DDRCH; ch++) { +		for (p = 0; p < NR_DDRPHY_PER_CH; p++) { +			printf("== Ch%d, PHY%d ==\n", ch, p); +			printf(" No: Name      : Address  : Data\n"); + +			phy = (struct ddrphy __iomem *)DDRPHY_BASE(ch, p); + +			REG_DUMP(ridr); +			REG_DUMP(pir); +			REG_DUMP(pgcr[0]); +			REG_DUMP(pgcr[1]); +			REG_DUMP(pgsr[0]); +			REG_DUMP(pgsr[1]); +			REG_DUMP(pllcr); +			REG_DUMP(ptr[0]); +			REG_DUMP(ptr[1]); +			REG_DUMP(ptr[2]); +			REG_DUMP(ptr[3]); +			REG_DUMP(ptr[4]); +			REG_DUMP(acmdlr); +			REG_DUMP(acbdlr); +			REG_DUMP(dxccr); +			REG_DUMP(dsgcr); +			REG_DUMP(dcr); +			REG_DUMP(dtpr[0]); +			REG_DUMP(dtpr[1]); +			REG_DUMP(dtpr[2]); +			REG_DUMP(mr0); +			REG_DUMP(mr1); +			REG_DUMP(mr2); +			REG_DUMP(mr3); +			REG_DUMP(dx[0].gcr); +			REG_DUMP(dx[0].gtr); +			REG_DUMP(dx[1].gcr); +			REG_DUMP(dx[1].gtr); +		} +	} +} + +static int do_ddr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ +	char *cmd = argv[1]; + +	if (argc == 1) +		cmd = "all"; + +	if (!strcmp(cmd, "wbdl") || !strcmp(cmd, "all")) +		wbdl_dump(); + +	if (!strcmp(cmd, "rbdl") || !strcmp(cmd, "all")) +		rbdl_dump(); + +	if (!strcmp(cmd, "wld") || !strcmp(cmd, "all")) +		wld_dump(); + +	if (!strcmp(cmd, "dqsgd") || !strcmp(cmd, "all")) +		dqsgd_dump(); + +	if (!strcmp(cmd, "mdl") || !strcmp(cmd, "all")) +		mdl_dump(); + +	if (!strcmp(cmd, "reg") || !strcmp(cmd, "all")) +		reg_dump(); + +	return 0; +} + +U_BOOT_CMD( +	ddr,	2,	1,	do_ddr, +	"UniPhier DDR PHY parameters dumper", +	"- dump all of the followings\n" +	"ddr wbdl - dump Write Bit Delay\n" +	"ddr rbdl - dump Read Bit Delay\n" +	"ddr wld - dump Write Leveling\n" +	"ddr dqsgd - dump DQS Gating Delay\n" +	"ddr mdl - dump Master Delay Line\n" +	"ddr reg - dump registers\n" +); | 
