umc-ph1-sld8.c 5.01 KB
Newer Older
1
/*
2
 * Copyright (C) 2011-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
3 4 5 6 7
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <common.h>
8
#include <linux/err.h>
9
#include <linux/io.h>
10
#include <linux/sizes.h>
11 12 13 14

#include "../init.h"
#include "ddrphy-regs.h"
#include "umc-regs.h"
15

16
static void umc_start_ssif(void __iomem *ssif_base)
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
{
	writel(0x00000000, ssif_base + 0x0000b004);
	writel(0xffffffff, ssif_base + 0x0000c004);
	writel(0x000fffcf, ssif_base + 0x0000c008);
	writel(0x00000001, ssif_base + 0x0000b000);
	writel(0x00000001, ssif_base + 0x0000c000);
	writel(0x03010101, ssif_base + UMC_MDMCHSEL);
	writel(0x03010100, ssif_base + UMC_DMDCHSEL);

	writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_FETCH);
	writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMQUE0);
	writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMWC0);
	writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMRC0);
	writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMQUE1);
	writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMWC1);
	writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMRC1);
	writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_WC);
	writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_RC);
	writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_DST);

	writel(0x00000001, ssif_base + UMC_CPURST);
	writel(0x00000001, ssif_base + UMC_IDSRST);
	writel(0x00000001, ssif_base + UMC_IXMRST);
	writel(0x00000001, ssif_base + UMC_MDMRST);
	writel(0x00000001, ssif_base + UMC_MDDRST);
	writel(0x00000001, ssif_base + UMC_SIORST);
	writel(0x00000001, ssif_base + UMC_VIORST);
	writel(0x00000001, ssif_base + UMC_FRCRST);
	writel(0x00000001, ssif_base + UMC_RGLRST);
	writel(0x00000001, ssif_base + UMC_AIORST);
	writel(0x00000001, ssif_base + UMC_DMDRST);
}

50 51
static void umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base,
			      int size, int freq)
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
{
#ifdef CONFIG_DDR_STANDARD
	writel(0x55990b11, dramcont + UMC_CMDCTLA);
	writel(0x16958944, dramcont + UMC_CMDCTLB);
#else
	writel(0x45990b11, dramcont + UMC_CMDCTLA);
	writel(0x16958924, dramcont + UMC_CMDCTLB);
#endif

	writel(0x5101046A, dramcont + UMC_INITCTLA);

	if (size == 1)
		writel(0x27028B0A, dramcont + UMC_INITCTLB);
	else if (size == 2)
		writel(0x38028B0A, dramcont + UMC_INITCTLB);

	writel(0x00FF00FF, dramcont + UMC_INITCTLC);
	writel(0x00000b51, dramcont + UMC_DRMMR0);
	writel(0x00000006, dramcont + UMC_DRMMR1);
	writel(0x00000290, dramcont + UMC_DRMMR2);

#ifdef CONFIG_DDR_STANDARD
	writel(0x00000000, dramcont + UMC_DRMMR3);
#else
	writel(0x00000800, dramcont + UMC_DRMMR3);
#endif

	if (size == 1)
		writel(0x00240512, dramcont + UMC_SPCCTLA);
	else if (size == 2)
		writel(0x00350512, dramcont + UMC_SPCCTLA);

	writel(0x00ff0006, dramcont + UMC_SPCCTLB);
	writel(0x000a00ac, dramcont + UMC_RDATACTL_D0);
	writel(0x04060806, dramcont + UMC_WDATACTL_D0);
	writel(0x04a02000, dramcont + UMC_DATASET);
	writel(0x00000000, ca_base + 0x2300);
	writel(0x00400020, dramcont + UMC_DCCGCTL);
	writel(0x00000003, dramcont + 0x7000);
	writel(0x0000004f, dramcont + 0x8000);
	writel(0x000000c3, dramcont + 0x8004);
	writel(0x00000077, dramcont + 0x8008);
	writel(0x0000003b, dramcont + UMC_DICGCTLA);
	writel(0x020a0808, dramcont + UMC_DICGCTLB);
	writel(0x00000004, dramcont + UMC_FLOWCTLG);
	writel(0x80000201, ca_base + 0xc20);
	writel(0x0801e01e, dramcont + UMC_FLOWCTLA);
	writel(0x00200000, dramcont + UMC_FLOWCTLB);
	writel(0x00004444, dramcont + UMC_FLOWCTLC);
	writel(0x200a0a00, dramcont + UMC_SPCSETB);
	writel(0x00000000, dramcont + UMC_SPCSETD);
	writel(0x00000520, dramcont + UMC_DFICUPDCTLA);
}

106
static int umc_init_sub(int freq, int size_ch0, int size_ch1)
107 108 109 110 111 112
{
	void __iomem *ssif_base = (void __iomem *)UMC_SSIF_BASE;
	void __iomem *ca_base0 = (void __iomem *)UMC_CA_BASE(0);
	void __iomem *ca_base1 = (void __iomem *)UMC_CA_BASE(1);
	void __iomem *dramcont0 = (void __iomem *)UMC_DRAMCONT_BASE(0);
	void __iomem *dramcont1 = (void __iomem *)UMC_DRAMCONT_BASE(1);
113 114
	void __iomem *phy0_0 = (void __iomem *)DDRPHY_BASE(0, 0);
	void __iomem *phy1_0 = (void __iomem *)DDRPHY_BASE(1, 0);
115 116 117 118 119 120 121 122

	umc_dram_init_start(dramcont0);
	umc_dram_init_start(dramcont1);
	umc_dram_init_poll(dramcont0);
	umc_dram_init_poll(dramcont1);

	writel(0x00000101, dramcont0 + UMC_DIOCTLA);

123
	ph1_sld8_ddrphy_init(phy0_0, freq, size_ch0);
124 125 126 127

	ddrphy_prepare_training(phy0_0, 0);
	ddrphy_training(phy0_0);

128 129
	writel(0x00000101, dramcont1 + UMC_DIOCTLA);

130
	ph1_sld8_ddrphy_init(phy1_0, freq, size_ch1);
131 132 133 134

	ddrphy_prepare_training(phy1_0, 1);
	ddrphy_training(phy1_0);

135 136 137 138 139 140 141 142
	umc_dramcont_init(dramcont0, ca_base0, size_ch0, freq);
	umc_dramcont_init(dramcont1, ca_base1, size_ch1, freq);

	umc_start_ssif(ssif_base);

	return 0;
}

143
int ph1_sld8_umc_init(const struct uniphier_board_data *bd)
144
{
145 146
	if ((bd->dram_ch[0].size == SZ_128M || bd->dram_ch[0].size == SZ_256M) &&
	    (bd->dram_ch[1].size == SZ_128M || bd->dram_ch[1].size == SZ_256M) &&
147
	    bd->dram_freq == 1333 &&
148
	    bd->dram_ch[0].width == 16 && bd->dram_ch[1].width == 16) {
149
		return umc_init_sub(bd->dram_freq,
150 151
				    bd->dram_ch[0].size / SZ_128M,
				    bd->dram_ch[1].size / SZ_128M);
152 153 154 155
	} else {
		pr_err("Unsupported DDR configuration\n");
		return -EINVAL;
	}
156
}