umc-ph1-ld4.c 5.61 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 11
#include <linux/sizes.h>
#include <mach/init.h>
12 13
#include <mach/umc-regs.h>
#include <mach/ddrphy-regs.h>
14

15
static void umc_start_ssif(void __iomem *ssif_base)
16 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
{
	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);
}

49 50
static void umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base,
			      int size, int freq)
51 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 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
{
	if (freq == 1333) {
		writel(0x45990b11, dramcont + UMC_CMDCTLA);
		writel(0x16958924, dramcont + UMC_CMDCTLB);
		writel(0x5101046A, dramcont + UMC_INITCTLA);

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

		writel(0x000FF0FF, dramcont + UMC_INITCTLC);
		writel(0x00000b51, dramcont + UMC_DRMMR0);
	} else if (freq == 1600) {
		writel(0x36BB0F17, dramcont + UMC_CMDCTLA);
		writel(0x18C6AA24, dramcont + UMC_CMDCTLB);
		writel(0x5101387F, dramcont + UMC_INITCTLA);

		if (size == 1)
			writel(0x2F030D3F, dramcont + UMC_INITCTLB);
		else if (size == 2)
			writel(0x43030D3F, dramcont + UMC_INITCTLB);

		writel(0x00FF00FF, dramcont + UMC_INITCTLC);
		writel(0x00000d71, dramcont + UMC_DRMMR0);
	}

	writel(0x00000006, dramcont + UMC_DRMMR1);

	if (freq == 1333)
		writel(0x00000290, dramcont + UMC_DRMMR2);
	else if (freq == 1600)
		writel(0x00000298, dramcont + UMC_DRMMR2);

	writel(0x00000800, dramcont + UMC_DRMMR3);

	if (freq == 1333) {
		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);
	} else if (freq == 1600) {
		if (size == 1)
			writel(0x002B0617, dramcont + UMC_SPCCTLA);
		else if (size == 2)
			writel(0x003F0617, dramcont + UMC_SPCCTLA);

		writel(0x00ff0008, dramcont + UMC_SPCCTLB);
		writel(0x000c00ae, 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(0x0000000f, dramcont + 0x8000);
	writel(0x000000c3, dramcont + 0x8004);
	writel(0x00000071, 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);
}

125
static int umc_init_sub(int freq, int size_ch0, int size_ch1)
126 127 128 129 130 131
{
	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);
132 133
	void __iomem *phy0_0 = (void __iomem *)DDRPHY_BASE(0, 0);
	void __iomem *phy1_0 = (void __iomem *)DDRPHY_BASE(1, 0);
134 135 136 137 138 139 140 141

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

142
	ph1_ld4_ddrphy_init(phy0_0, freq, size_ch0);
143 144 145 146

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

147 148
	writel(0x00000101, dramcont1 + UMC_DIOCTLA);

149
	ph1_ld4_ddrphy_init(phy1_0, freq, size_ch1);
150 151 152 153

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

154 155 156 157 158 159 160 161
	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;
}

162
int ph1_ld4_umc_init(const struct uniphier_board_data *bd)
163
{
164 165 166 167 168 169 170 171 172 173 174
	if ((bd->dram_ch0_size == SZ_128M || bd->dram_ch0_size == SZ_256M) &&
	    (bd->dram_ch1_size == SZ_128M || bd->dram_ch1_size == SZ_256M) &&
	    (bd->dram_freq == 1333 || bd->dram_freq == 1600) &&
	    bd->dram_ch0_width == 16 && bd->dram_ch1_width == 16) {
		return umc_init_sub(bd->dram_freq,
				    bd->dram_ch0_size / SZ_128M,
				    bd->dram_ch1_size / SZ_128M);
	} else {
		pr_err("Unsupported DDR configuration\n");
		return -EINVAL;
	}
175
}