summaryrefslogtreecommitdiff
path: root/arch/arm/include/asm/arch-sunxi/dram_sun50i_a133.h
blob: a5fc6ad36560b8c66431b97294e96dbec211c624 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
49
50
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
// SPDX-License-Identifier:	GPL-2.0+
/*
 * A133 dram controller register and constant defines
 *
 * (C) Copyright 2024  MasterR3C0RD <masterr3c0rd@epochal.quest>
 */

#ifndef _SUNXI_DRAM_SUN50I_A133_H
#define _SUNXI_DRAM_SUN50I_A133_H

#include <linux/bitops.h>

enum sunxi_dram_type {
	SUNXI_DRAM_TYPE_DDR3 = 3,
	SUNXI_DRAM_TYPE_DDR4,
	SUNXI_DRAM_TYPE_LPDDR3 = 7,
	SUNXI_DRAM_TYPE_LPDDR4
};

static inline int ns_to_t(int nanoseconds)
{
	const unsigned int ctrl_freq = CONFIG_DRAM_CLK / 2;

	return DIV_ROUND_UP(ctrl_freq * nanoseconds, 1000);
}

/* MBUS part is largely the same as in H6, except for one special register */
#define MCTL_COM_UNK_008	0x008
/* NOTE: This register has the same importance as mctl_ctl->clken in H616 */
#define MCTL_COM_MAER0		0x020

/*
 * Controller registers seems to be the same or at least very similar
 * to those in H6.
 */
struct sunxi_mctl_ctl_reg {
	u32 mstr; 			/* 0x000 */
	u32 statr; 			/* 0x004 unused */
	u32 mstr1; 			/* 0x008 unused */
	u32 clken; 			/* 0x00c */
	u32 mrctrl0; 			/* 0x010 unused */
	u32 mrctrl1; 			/* 0x014 unused */
	u32 mrstatr; 			/* 0x018 unused */
	u32 mrctrl2; 			/* 0x01c unused */
	u32 derateen; 			/* 0x020 unused */
	u32 derateint; 			/* 0x024 unused */
	u8 reserved_0x028[8]; 		/* 0x028 */
	u32 pwrctl; 			/* 0x030 unused */
	u32 pwrtmg; 			/* 0x034 unused */
	u32 hwlpctl; 			/* 0x038 unused */
	u8 reserved_0x03c[20];		/* 0x03c */
	u32 rfshctl0;			/* 0x050 unused */
	u32 rfshctl1;			/* 0x054 unused */
	u8 reserved_0x058[8];		/* 0x05c */
	u32 rfshctl3;			/* 0x060 */
	u32 rfshtmg;			/* 0x064 */
	u8 reserved_0x068[104];		/* 0x068 */
	u32 init[8];			/* 0x0d0 */
	u32 dimmctl;			/* 0x0f0 unused */
	u32 rankctl;			/* 0x0f4 */
	u8 reserved_0x0f8[8];		/* 0x0f8 */
	u32 dramtmg[17];		/* 0x100 */
	u8 reserved_0x144[60];		/* 0x144 */
	u32 zqctl[3];			/* 0x180 */
	u32 zqstat;			/* 0x18c unused */
	u32 dfitmg0;			/* 0x190 */
	u32 dfitmg1;			/* 0x194 */
	u32 dfilpcfg[2];		/* 0x198 unused */
	u32 dfiupd[3];			/* 0x1a0 */
	u32 reserved_0x1ac;		/* 0x1ac */
	u32 dfimisc;			/* 0x1b0 */
	u32 dfitmg2;			/* 0x1b4 unused */
	u32 dfitmg3;			/* 0x1b8 unused */
	u32 dfistat;			/* 0x1bc */
	u32 dbictl;			/* 0x1c0 */
	u8 reserved_0x1c4[60];		/* 0x1c4 */
	u32 addrmap[12];		/* 0x200 */
	u8 reserved_0x230[16];		/* 0x230 */
	u32 odtcfg;			/* 0x240 */
	u32 odtmap;			/* 0x244 */
	u8 reserved_0x248[8];		/* 0x248 */
	u32 sched[2];			/* 0x250 */
	u8 reserved_0x258[180]; 	/* 0x258 */
	u32 dbgcmd;			/* 0x30c unused */
	u32 dbgstat;			/* 0x310 unused */
	u8 reserved_0x314[12];		/* 0x314 */
	u32 swctl;			/* 0x320 */
	u32 swstat;			/* 0x324 */
	u8 reserved_0x328[7768];	/* 0x328 */
	u32 unk_0x2180;			/* 0x2180 */
	u8 reserved_0x2184[188];	/* 0x2184 */
	u32 unk_0x2240;			/* 0x2240 */
	u8 reserved_0x2244[3900];	/* 0x2244 */
	u32 unk_0x3180;			/* 0x3180 */
	u8 reserved_0x3184[188];	/* 0x3184 */
	u32 unk_0x3240;			/* 0x3240 */
	u8 reserved_0x3244[3900];	/* 0x3244 */
	u32 unk_0x4180;			/* 0x4180 */
	u8 reserved_0x4184[188];	/* 0x4184 */
	u32 unk_0x4240;			/* 0x4240 */
};

check_member(sunxi_mctl_ctl_reg, swstat, 0x324);
check_member(sunxi_mctl_ctl_reg, unk_0x4240, 0x4240);

#define MSTR_DEVICETYPE_DDR3	BIT(0)
#define MSTR_DEVICETYPE_LPDDR2	BIT(2)
#define MSTR_DEVICETYPE_LPDDR3	BIT(3)
#define MSTR_DEVICETYPE_DDR4	BIT(4)
#define MSTR_DEVICETYPE_LPDDR4	BIT(5)
#define MSTR_DEVICETYPE_MASK	GENMASK(5, 0)
#define MSTR_GEARDOWNMODE	BIT(0)		/* Same as MSTR_DEVICETYPE_DDR3, only used for DDR4 */
#define MSTR_2TMODE		BIT(10)
#define MSTR_BUSWIDTH_FULL	(0 << 12)
#define MSTR_BUSWIDTH_HALF	(1 << 12)
#define MSTR_ACTIVE_RANKS(x)	(((x == 1) ? 3 : 1) << 24)
#define MSTR_BURST_LENGTH(x)	(((x) >> 1) << 16)
#define MSTR_DEVICECONFIG_X32	(3 << 30)

#define TPR10_CA_BIT_DELAY	BIT(16)
#define TPR10_DX_BIT_DELAY0	BIT(17)
#define TPR10_DX_BIT_DELAY1	BIT(18)
#define TPR10_WRITE_LEVELING	BIT(20)
#define TPR10_READ_CALIBRATION	BIT(21)
#define TPR10_READ_TRAINING	BIT(22)
#define TPR10_WRITE_TRAINING	BIT(23)

/* MRCTRL constants */
#define MRCTRL0_MR_RANKS_ALL	(3 << 4)
#define MRCTRL0_MR_ADDR(x)	(x << 12)
#define MRCTRL0_MR_WR		BIT(31)

#define MRCTRL1_MR_ADDR(x)	(x << 8)
#define MRCTRL1_MR_DATA(x)	(x)

/* ADDRMAP constants */
#define ADDRMAP_DISABLED_3F_B(b)	(0x3f + b)
#define ADDRMAP_DISABLED_1F_B(b)	(0x1f + b)
#define ADDRMAP_DISABLED_0F_B(b)	(0x0f + b)

#define _ADDRMAP_VALUE(a,x,b)		(((a) - b) << (x * 8))

/*
 * Bx = internal base
 * The selected HIF address bit for each address bit is determined
 * by adding the internal base to the value of each field
 * */

#define ADDRMAP0_CS0_B6(v)	_ADDRMAP_VALUE(v, 0, 6)

#define ADDRMAP1_BANK0_B2(v) 	_ADDRMAP_VALUE(v, 0, 2)
#define ADDRMAP1_BANK1_B3(v)	_ADDRMAP_VALUE(v, 1, 3)
#define ADDRMAP1_BANK2_B4(v)	_ADDRMAP_VALUE(v, 2, 4)

#define ADDRMAP2_COL2_B2(v)	_ADDRMAP_VALUE(v, 0, 2)
#define ADDRMAP2_COL3_B3(v)	_ADDRMAP_VALUE(v, 1, 3)
#define ADDRMAP2_COL4_B4(v)	_ADDRMAP_VALUE(v, 2, 4)
#define ADDRMAP2_COL5_B5(v)	_ADDRMAP_VALUE(v, 3, 5)

#define ADDRMAP3_COL6_B6(v)	_ADDRMAP_VALUE(v, 0, 6)
#define ADDRMAP3_COL7_B7(v)	_ADDRMAP_VALUE(v, 1, 7)
#define ADDRMAP3_COL8_B8(v)	_ADDRMAP_VALUE(v, 2, 8)
#define ADDRMAP3_COL9_B9(v)	_ADDRMAP_VALUE(v, 3, 9)

#define ADDRMAP4_COL10_B10(v)	_ADDRMAP_VALUE(v, 0, 10)
#define ADDRMAP4_COL11_B11(v)	_ADDRMAP_VALUE(v, 1, 11)

#define ADDRMAP5_ROW0_B6(v)	_ADDRMAP_VALUE(v, 0, 6)
#define ADDRMAP5_ROW1_B7(v)	_ADDRMAP_VALUE(v, 1, 7)
#define ADDRMAP5_ROW2_10_B8(v)	_ADDRMAP_VALUE(v, 2, 8)
#define ADDRMAP5_ROW11_B17(v)	_ADDRMAP_VALUE(v, 3, 17)

#define ADDRMAP6_ROW12_B18(v)	_ADDRMAP_VALUE(v, 0, 18)
#define ADDRMAP6_ROW13_B19(v)	_ADDRMAP_VALUE(v, 1, 19)
#define ADDRMAP6_ROW14_B20(v)	_ADDRMAP_VALUE(v, 2, 20)
#define ADDRMAP6_ROW15_B21(v)	_ADDRMAP_VALUE(v, 3, 21)

#define ADDRMAP7_ROW16_B22(v)	_ADDRMAP_VALUE(v, 0, 22)
#define ADDRMAP7_ROW17_B23(v)	_ADDRMAP_VALUE(v, 1, 23)

#define ADDRMAP8_BG0_B2(v)	_ADDRMAP_VALUE(v, 0, 2)
#define ADDRMAP8_BG1_B3(v)	_ADDRMAP_VALUE(v, 1, 3)

/* These are only used if ADDRMAP5_ROW_BITS_2_10 = ADDRMAP_DISABLED_0F */
#define ADDRMAP9_ROW2_B8(v)	_ADDRMAP_VALUE(v, 0, 8)
#define ADDRMAP9_ROW3_B9(v)	_ADDRMAP_VALUE(v, 1, 9)
#define ADDRMAP9_ROW4_B10(v)	_ADDRMAP_VALUE(v, 2, 10)
#define ADDRMAP9_ROW5_B11(v)	_ADDRMAP_VALUE(v, 3, 11)

#define ADDRMAP10_ROW6_B12(v)	_ADDRMAP_VALUE(v, 0, 12)
#define ADDRMAP10_ROW7_B13(v)	_ADDRMAP_VALUE(v, 1, 13)
#define ADDRMAP10_ROW8_B14(v)	_ADDRMAP_VALUE(v, 2, 14)
#define ADDRMAP10_ROW9_B15(v)	_ADDRMAP_VALUE(v, 3, 15)

#define ADDRMAP11_ROW10_B16(v)	_ADDRMAP_VALUE(v, 0, 16)

struct dram_para {
	uint32_t clk;
	enum sunxi_dram_type type;
	uint32_t dx_odt;
	uint32_t dx_dri;
	uint32_t ca_dri;
	uint32_t para0;
	uint32_t mr11;
	uint32_t mr12;
	uint32_t mr13;
	uint32_t mr14;
	uint32_t tpr1;
	uint32_t tpr2;
	uint32_t tpr3;
	uint32_t tpr6;
	uint32_t tpr10;
	uint32_t tpr11;
	uint32_t tpr12;
	uint32_t tpr13;
	uint32_t tpr14;
};

void mctl_set_timing_params(const struct dram_para *para);

struct dram_config {
	u8 cols;		/* Column bits */
	u8 rows;		/* Row bits */
	u8 ranks;		/* Rank bits (different from H616!) */
	u8 banks;		/* Bank bits */
	u8 bankgrps;		/* Bank group bits */
	u8 bus_full_width;	/* 1 = x32, 0 = x16 */
};

#endif /* _SUNXI_DRAM_SUN50I_A133_H */