umc-ph1-pro4.c 5.54 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 50 51 52 53 54 55 56 57 58
{
	writel(0x00000001, ssif_base + 0x0000b004);
	writel(0xffffffff, ssif_base + 0x0000c004);
	writel(0x07ffffff, ssif_base + 0x0000c008);
	writel(0x00000001, ssif_base + 0x0000b000);
	writel(0x00000001, ssif_base + 0x0000c000);

	writel(0x03010100, ssif_base + UMC_HDMCHSEL);
	writel(0x03010101, ssif_base + UMC_MDMCHSEL);
	writel(0x03010100, ssif_base + UMC_DVCCHSEL);
	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(0x00000000, ssif_base + 0x0000c044);		/* DCGIV_SSIF_REG */

	writel(0x00000001, ssif_base + UMC_CPURST);
	writel(0x00000001, ssif_base + UMC_IDSRST);
	writel(0x00000001, ssif_base + UMC_IXMRST);
	writel(0x00000001, ssif_base + UMC_HDMRST);
	writel(0x00000001, ssif_base + UMC_MDMRST);
	writel(0x00000001, ssif_base + UMC_HDDRST);
	writel(0x00000001, ssif_base + UMC_MDDRST);
	writel(0x00000001, ssif_base + UMC_SIORST);
	writel(0x00000001, ssif_base + UMC_GIORST);
	writel(0x00000001, ssif_base + UMC_HD2RST);
	writel(0x00000001, ssif_base + UMC_VIORST);
	writel(0x00000001, ssif_base + UMC_DVCRST);
	writel(0x00000001, ssif_base + UMC_RGLRST);
	writel(0x00000001, ssif_base + UMC_VPERST);
	writel(0x00000001, ssif_base + UMC_AIORST);
	writel(0x00000001, ssif_base + UMC_DMDRST);
}

59 60
static void umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base,
			      int size, int freq)
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
{
	writel(0x66bb0f17, dramcont + UMC_CMDCTLA);
	writel(0x18c6aa44, dramcont + UMC_CMDCTLB);
	writel(0x5101387f, dramcont + UMC_INITCTLA);
	writel(0x43030d3f, dramcont + UMC_INITCTLB);
	writel(0x00ff00ff, dramcont + UMC_INITCTLC);
	writel(0x00000d71, dramcont + UMC_DRMMR0);
	writel(0x00000006, dramcont + UMC_DRMMR1);
	writel(0x00000298, dramcont + UMC_DRMMR2);
	writel(0x00000000, dramcont + UMC_DRMMR3);
	writel(0x003f0617, dramcont + UMC_SPCCTLA);
	writel(0x00ff0008, dramcont + UMC_SPCCTLB);
	writel(0x000c00ae, dramcont + UMC_RDATACTL_D0);
	writel(0x000c00ae, dramcont + UMC_RDATACTL_D1);
	writel(0x04060802, dramcont + UMC_WDATACTL_D0);
	writel(0x04060802, dramcont + UMC_WDATACTL_D1);
	writel(0x04a02000, dramcont + UMC_DATASET);
	writel(0x00000000, ca_base + 0x2300);
	writel(0x00400020, dramcont + UMC_DCCGCTL);
	writel(0x0000000f, dramcont + 0x7000);
	writel(0x0000000f, dramcont + 0x8000);
	writel(0x000000c3, dramcont + 0x8004);
	writel(0x00000071, dramcont + 0x8008);
	writel(0x00000004, dramcont + UMC_FLOWCTLG);
	writel(0x00000000, dramcont + 0x0060);
	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(0x00010000, dramcont + UMC_SPCSETD);
	writel(0x80000020, dramcont + UMC_DFICUPDCTLA);
}

95
static int umc_init_sub(int freq, int size_ch0, int size_ch1)
96 97 98 99 100 101
{
	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);
102 103 104 105
	void __iomem *phy0_0 = (void __iomem *)DDRPHY_BASE(0, 0);
	void __iomem *phy0_1 = (void __iomem *)DDRPHY_BASE(0, 1);
	void __iomem *phy1_0 = (void __iomem *)DDRPHY_BASE(1, 0);
	void __iomem *phy1_1 = (void __iomem *)DDRPHY_BASE(1, 1);
106 107 108 109 110 111 112 113

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

114
	ph1_pro4_ddrphy_init(phy0_0, freq, size_ch0);
115 116 117 118

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

119 120
	writel(0x00000103, dramcont0 + UMC_DIOCTLA);

121
	ph1_pro4_ddrphy_init(phy0_1, freq, size_ch0);
122 123 124 125

	ddrphy_prepare_training(phy0_1, 1);
	ddrphy_training(phy0_1);

126 127
	writel(0x00000101, dramcont1 + UMC_DIOCTLA);

128
	ph1_pro4_ddrphy_init(phy1_0, freq, size_ch1);
129 130 131 132

	ddrphy_prepare_training(phy1_0, 0);
	ddrphy_training(phy1_0);

133 134
	writel(0x00000103, dramcont1 + UMC_DIOCTLA);

135
	ph1_pro4_ddrphy_init(phy1_1, freq, size_ch1);
136 137 138 139

	ddrphy_prepare_training(phy1_1, 1);
	ddrphy_training(phy1_1);

140 141 142 143 144 145 146 147
	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;
}

148
int ph1_pro4_umc_init(const struct uniphier_board_data *bd)
149
{
150 151 152 153 154 155 156 157 158 159 160 161
	if (((bd->dram_ch0_size == SZ_512M && bd->dram_ch0_width == 32) ||
	     (bd->dram_ch0_size == SZ_256M && bd->dram_ch0_width == 16)) &&
	    ((bd->dram_ch1_size == SZ_512M && bd->dram_ch1_width == 32) ||
	     (bd->dram_ch1_size == SZ_256M && bd->dram_ch1_width == 16)) &&
	    bd->dram_freq == 1600) {
		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;
	}
162
}