Skip to content

Commit

Permalink
ARM: uniphier: rework existing DDR PHY code to reuse for LD11 SoC
Browse files Browse the repository at this point in the history
The DDR PHY register view of LD11 is slightly different from that
of LD4/Pro4/sLD8, but it will be possible to share the register
macros (and I want to re-use as much code as possible).  Change
the code in the more flexible form.

Signed-off-by: Masahiro Yamada <[email protected]>
  • Loading branch information
masahir0y committed Oct 29, 2016
1 parent 9c5313d commit 6dd34ae
Show file tree
Hide file tree
Showing 8 changed files with 302 additions and 294 deletions.
142 changes: 78 additions & 64 deletions arch/arm/mach-uniphier/dram/cmd_ddrphy.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <linux/sizes.h>

#include "../soc-info.h"
#include "ddrphy-init.h"
#include "ddrphy-regs.h"

/* Select either decimal or hexadecimal */
Expand Down Expand Up @@ -40,38 +41,43 @@ static unsigned long uniphier_sld8_base[] = {
0 /* sentinel */
};

static u32 read_bdl(struct ddrphy_datx8 __iomem *dx, int index)
static void print_bdl(void __iomem *reg, int n)
{
return (readl(&dx->bdlr[index / 5]) >> (index % 5 * 6)) & 0x3f;
u32 val = readl(reg);
int i;

for (i = 0; i < n; i++)
printf(FS PRINTF_FORMAT, (val >> i * 6) & 0x3f);
}

static void dump_loop(unsigned long *base,
void (*callback)(struct ddrphy_datx8 __iomem *))
void (*callback)(void __iomem *))
{
struct ddrphy __iomem *phy;
void __iomem *phy_base, *dx_base;
int p, dx;

for (p = 0; *base; base++, p++) {
phy = ioremap(*base, SZ_4K);
phy_base = ioremap(*base, SZ_4K);
dx_base = phy_base + PHY_DX_BASE;

for (dx = 0; dx < NR_DATX8_PER_DDRPHY; dx++) {
printf("PHY%dDX%d:", p, dx);
(*callback)(&phy->dx[dx]);
(*callback)(dx_base);
dx_base += PHY_DX_STRIDE;
printf("\n");
}

iounmap(phy);
iounmap(phy_base);
}
}

static void __wbdl_dump(struct ddrphy_datx8 __iomem *dx)
static void __wbdl_dump(void __iomem *dx_base)
{
int i;
print_bdl(dx_base + PHY_DX_BDLR0, 5);
print_bdl(dx_base + PHY_DX_BDLR1, 5);

for (i = 0; i < 10; i++)
printf(FS PRINTF_FORMAT, read_bdl(dx, i));

printf(FS "(+" PRINTF_FORMAT ")", readl(&dx->lcdlr[1]) & 0xff);
printf(FS "(+" PRINTF_FORMAT ")",
readl(dx_base + PHY_DX_LCDLR1) & 0xff);
}

static void wbdl_dump(unsigned long *base)
Expand All @@ -82,14 +88,13 @@ static void wbdl_dump(unsigned long *base)
dump_loop(base, &__wbdl_dump);
}

static void __rbdl_dump(struct ddrphy_datx8 __iomem *dx)
static void __rbdl_dump(void __iomem *dx_base)
{
int i;

for (i = 15; i < 24; i++)
printf(FS PRINTF_FORMAT, read_bdl(dx, i));
print_bdl(dx_base + PHY_DX_BDLR3, 5);
print_bdl(dx_base + PHY_DX_BDLR4, 4);

printf(FS "(+" PRINTF_FORMAT ")", (readl(&dx->lcdlr[1]) >> 8) & 0xff);
printf(FS "(+" PRINTF_FORMAT ")",
(readl(dx_base + PHY_DX_LCDLR1) >> 8) & 0xff);
}

static void rbdl_dump(unsigned long *base)
Expand All @@ -100,11 +105,11 @@ static void rbdl_dump(unsigned long *base)
dump_loop(base, &__rbdl_dump);
}

static void __wld_dump(struct ddrphy_datx8 __iomem *dx)
static void __wld_dump(void __iomem *dx_base)
{
int rank;
u32 lcdlr0 = readl(&dx->lcdlr[0]);
u32 gtr = readl(&dx->gtr);
u32 lcdlr0 = readl(dx_base + PHY_DX_LCDLR0);
u32 gtr = readl(dx_base + PHY_DX_GTR);

for (rank = 0; rank < 4; rank++) {
u32 wld = (lcdlr0 >> (8 * rank)) & 0xff; /* Delay */
Expand All @@ -123,11 +128,11 @@ static void wld_dump(unsigned long *base)
dump_loop(base, &__wld_dump);
}

static void __dqsgd_dump(struct ddrphy_datx8 __iomem *dx)
static void __dqsgd_dump(void __iomem *dx_base)
{
int rank;
u32 lcdlr2 = readl(&dx->lcdlr[2]);
u32 gtr = readl(&dx->gtr);
u32 lcdlr2 = readl(dx_base + PHY_DX_LCDLR2);
u32 gtr = readl(dx_base + PHY_DX_GTR);

for (rank = 0; rank < 4; rank++) {
u32 dqsgd = (lcdlr2 >> (8 * rank)) & 0xff; /* Delay */
Expand All @@ -145,10 +150,10 @@ static void dqsgd_dump(unsigned long *base)
dump_loop(base, &__dqsgd_dump);
}

static void __mdl_dump(struct ddrphy_datx8 __iomem *dx)
static void __mdl_dump(void __iomem *dx_base)
{
int i;
u32 mdl = readl(&dx->mdlr);
u32 mdl = readl(dx_base + PHY_DX_MDLR);
for (i = 0; i < 3; i++)
printf(FS PRINTF_FORMAT, (mdl >> (8 * i)) & 0xff);
}
Expand All @@ -161,53 +166,62 @@ static void mdl_dump(unsigned long *base)
dump_loop(base, &__mdl_dump);
}

#define REG_DUMP(x) \
{ u32 __iomem *p = &phy->x; printf("%3d: %-10s: %p : %08x\n", \
p - (u32 *)phy, #x, p, readl(p)); }
#define REG_DUMP(x) \
{ int ofst = PHY_ ## x; void __iomem *reg = phy_base + ofst; \
printf("%3d: %-10s: %p : %08x\n", \
ofst >> PHY_REG_SHIFT, #x, reg, readl(reg)); }

#define DX_REG_DUMP(dx, x) \
{ int ofst = PHY_DX_BASE + PHY_DX_STRIDE * (dx) + \
PHY_DX_## x; \
void __iomem *reg = phy_base + ofst; \
printf("%3d: DX%d%-7s: %p : %08x\n", \
ofst >> PHY_REG_SHIFT, (dx), #x, reg, readl(reg)); }

static void reg_dump(unsigned long *base)
{
struct ddrphy __iomem *phy;
int p;
void __iomem *phy_base;
int p, dx;

printf("\n--- DDR PHY registers ---\n");

for (p = 0; *base; base++, p++) {
phy = ioremap(*base, SZ_4K);
phy_base = ioremap(*base, SZ_4K);

printf("== PHY%d (base: %p) ==\n", p, phy);
printf("== PHY%d (base: %p) ==\n", p, phy_base);
printf(" No: Name : Address : Data\n");

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);

iounmap(phy);
REG_DUMP(RIDR);
REG_DUMP(PIR);
REG_DUMP(PGCR0);
REG_DUMP(PGCR1);
REG_DUMP(PGSR0);
REG_DUMP(PGSR1);
REG_DUMP(PLLCR);
REG_DUMP(PTR0);
REG_DUMP(PTR1);
REG_DUMP(PTR2);
REG_DUMP(PTR3);
REG_DUMP(PTR4);
REG_DUMP(ACMDLR);
REG_DUMP(ACBDLR);
REG_DUMP(DXCCR);
REG_DUMP(DSGCR);
REG_DUMP(DCR);
REG_DUMP(DTPR0);
REG_DUMP(DTPR1);
REG_DUMP(DTPR2);
REG_DUMP(MR0);
REG_DUMP(MR1);
REG_DUMP(MR2);
REG_DUMP(MR3);

for (dx = 0; dx < NR_DATX8_PER_DDRPHY; dx++) {
DX_REG_DUMP(dx, GCR);
DX_REG_DUMP(dx, GTR);
}

iounmap(phy_base);
}
}

Expand Down
20 changes: 20 additions & 0 deletions arch/arm/mach-uniphier/dram/ddrphy-init.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright (C) 2016 Socionext Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*/

#ifndef ARCH_DDRPHY_INIT_H
#define ARCH_DDRPHY_INTT_H

#include <linux/compiler.h>
#include <linux/types.h>

/* for LD4, Pro4, sLD8 */
#define NR_DATX8_PER_DDRPHY 2

int uniphier_ld4_ddrphy_init(void __iomem *phy_base, int freq, bool ddr3plus);
void ddrphy_prepare_training(void __iomem *phy_base, int rank);
int ddrphy_training(void __iomem *phy_base);

#endif /* ARCH_DDRPHY_INT_H */
50 changes: 25 additions & 25 deletions arch/arm/mach-uniphier/dram/ddrphy-ld4.c
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
/*
* Copyright (C) 2014-2015 Masahiro Yamada <[email protected]>
* Copyright (C) 2014 Panasonic Corporation
* Copyright (C) 2015-2016 Socionext Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*/

#include <common.h>
#include <linux/err.h>
#include <linux/types.h>
#include <linux/io.h>

#include "ddrphy-init.h"
#include "ddrphy-regs.h"

enum dram_freq {
Expand All @@ -27,8 +28,7 @@ static u32 ddrphy_dtpr2[DRAM_FREQ_NR] = {0x5002c200, 0xa00214f8};
static u32 ddrphy_mr0[DRAM_FREQ_NR] = {0x00000b51, 0x00000d71};
static u32 ddrphy_mr2[DRAM_FREQ_NR] = {0x00000290, 0x00000298};

int uniphier_ld4_ddrphy_init(struct ddrphy __iomem *phy, int freq,
bool ddr3plus)
int uniphier_ld4_ddrphy_init(void __iomem *phy_base, int freq, bool ddr3plus)
{
enum dram_freq freq_e;
u32 tmp;
Expand All @@ -45,34 +45,34 @@ int uniphier_ld4_ddrphy_init(struct ddrphy __iomem *phy, int freq,
return -EINVAL;
}

writel(0x0300c473, &phy->pgcr[1]);
writel(ddrphy_ptr0[freq_e], &phy->ptr[0]);
writel(ddrphy_ptr1[freq_e], &phy->ptr[1]);
writel(0x00083DEF, &phy->ptr[2]);
writel(ddrphy_ptr3[freq_e], &phy->ptr[3]);
writel(ddrphy_ptr4[freq_e], &phy->ptr[4]);
writel(0xF004001A, &phy->dsgcr);
writel(0x0300c473, phy_base + PHY_PGCR1);
writel(ddrphy_ptr0[freq_e], phy_base + PHY_PTR0);
writel(ddrphy_ptr1[freq_e], phy_base + PHY_PTR1);
writel(0x00083DEF, phy_base + PHY_PTR2);
writel(ddrphy_ptr3[freq_e], phy_base + PHY_PTR3);
writel(ddrphy_ptr4[freq_e], phy_base + PHY_PTR4);
writel(0xF004001A, phy_base + PHY_DSGCR);

/* change the value of the on-die pull-up/pull-down registors */
tmp = readl(&phy->dxccr);
tmp = readl(phy_base + PHY_DXCCR);
tmp &= ~0x0ee0;
tmp |= DXCCR_DQSNRES_688_OHM | DXCCR_DQSRES_688_OHM;
writel(tmp, &phy->dxccr);
tmp |= PHY_DXCCR_DQSNRES_688_OHM | PHY_DXCCR_DQSRES_688_OHM;
writel(tmp, phy_base + PHY_DXCCR);

writel(0x0000040B, &phy->dcr);
writel(ddrphy_dtpr0[freq_e], &phy->dtpr[0]);
writel(ddrphy_dtpr1[freq_e], &phy->dtpr[1]);
writel(ddrphy_dtpr2[freq_e], &phy->dtpr[2]);
writel(ddrphy_mr0[freq_e], &phy->mr0);
writel(0x00000006, &phy->mr1);
writel(ddrphy_mr2[freq_e], &phy->mr2);
writel(ddr3plus ? 0x00000800 : 0x00000000, &phy->mr3);
writel(0x0000040B, phy_base + PHY_DCR);
writel(ddrphy_dtpr0[freq_e], phy_base + PHY_DTPR0);
writel(ddrphy_dtpr1[freq_e], phy_base + PHY_DTPR1);
writel(ddrphy_dtpr2[freq_e], phy_base + PHY_DTPR2);
writel(ddrphy_mr0[freq_e], phy_base + PHY_MR0);
writel(0x00000006, phy_base + PHY_MR1);
writel(ddrphy_mr2[freq_e], phy_base + PHY_MR2);
writel(ddr3plus ? 0x00000800 : 0x00000000, phy_base + PHY_MR3);

while (!(readl(&phy->pgsr[0]) & PGSR0_IDONE))
while (!(readl(phy_base + PHY_PGSR0) & PHY_PGSR0_IDONE))
;

writel(0x0300C473, &phy->pgcr[1]);
writel(0x0000005D, &phy->zq[0].cr[1]);
writel(0x0300C473, phy_base + PHY_PGCR1);
writel(0x0000005D, phy_base + PHY_ZQ_BASE + PHY_ZQ_CR1);

return 0;
}
Loading

0 comments on commit 6dd34ae

Please sign in to comment.