summaryrefslogtreecommitdiff
path: root/board/sheldon/simpc8313/sdram.c
blob: 7c12fe851cb3f279bd52d95fa7d979282680516d (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
/*
 * Copyright (C) Freescale Semiconductor, Inc. 2006-2007
 * Copyright (C) Sheldon Instruments, Inc. 2008
 *
 * Author: Ron Madrid <info@sheldoninst.com>
 *
 * (C) Copyright 2006
 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <common.h>
#include <mpc83xx.h>
#include <spd_sdram.h>
#include <asm/bitops.h>
#include <asm/io.h>
#include <asm/processor.h>
#include <asm/mmu.h>

DECLARE_GLOBAL_DATA_PTR;

static long fixed_sdram(void);

#if defined(CONFIG_NAND_SPL)
void si_wait_i2c(void)
{
	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;

	while (!(__raw_readb(&im->i2c[0].sr) & 0x02))
		;

	__raw_writeb(0x00, &im->i2c[0].sr);

	sync();

	return;
}

void si_read_i2c(u32 lbyte, int count, u8 *buffer)
{
	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
	u32 i;
	u8 chip = 0x50 << 1; /* boot sequencer I2C */
	u32 ubyte = (lbyte & 0xff00) >> 8;

	lbyte &= 0xff;

	/*
	 * Set up controller
	 */
	__raw_writeb(0x3f, &im->i2c[0].fdr);
	__raw_writeb(0x00, &im->i2c[0].adr);
	__raw_writeb(0x00, &im->i2c[0].sr);
	__raw_writeb(0x00, &im->i2c[0].dr);

	while (__raw_readb(&im->i2c[0].sr) & 0x20)
		;

	/*
	 * Writing address to device
	 */
	__raw_writeb(0xb0, &im->i2c[0].cr);
	sync();
	__raw_writeb(chip, &im->i2c[0].dr);
	si_wait_i2c();

	__raw_writeb(0xb0, &im->i2c[0].cr);
	sync();
	__raw_writeb(ubyte, &im->i2c[0].dr);
	si_wait_i2c();

	__raw_writeb(lbyte, &im->i2c[0].dr);
	si_wait_i2c();

	__raw_writeb(0xb4, &im->i2c[0].cr);
	sync();
	__raw_writeb(chip + 1, &im->i2c[0].dr);
	si_wait_i2c();

	__raw_writeb(0xa0, &im->i2c[0].cr);
	sync();

	/*
	 * Dummy read
	 */
	__raw_readb(&im->i2c[0].dr);

	si_wait_i2c();

	/*
	 * Read actual data
	 */
	for (i = 0; i < count; i++)
	{
		if (i == (count - 2))	/* Reached next to last byte, No ACK */
			__raw_writeb(0xa8, &im->i2c[0].cr);
		if (i == (count - 1))	/* Reached last byte, STOP */
			__raw_writeb(0x88, &im->i2c[0].cr);

		/* Read byte of data */
		buffer[i] = __raw_readb(&im->i2c[0].dr);

		if (i == (count - 1))
			break;
		si_wait_i2c();
	}

	return;
}
#endif /* CONFIG_NAND_SPL */

phys_size_t initdram(int board_type)
{
	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
	volatile fsl_lbc_t *lbc = &im->im_lbc;
	u32 msize;

	if ((__raw_readl(&im->sysconf.immrbar) & IMMRBAR_BASE_ADDR) != (u32) im)
		return -1;

	/* DDR SDRAM - Main SODIMM */
	__raw_writel(CONFIG_SYS_DDR_BASE & LAWBAR_BAR, &im->sysconf.ddrlaw[0].bar);

	msize = fixed_sdram();

	/* Local Bus setup lbcr and mrtpr */
	__raw_writel(CONFIG_SYS_LBC_LBCR, &lbc->lbcr);
	__raw_writel(CONFIG_SYS_LBC_MRTPR, &lbc->mrtpr);
	sync();

	/* return total bus SDRAM size(bytes)  -- DDR */
	return (msize * 1024 * 1024);
}

/*************************************************************************
 *  fixed sdram init -- reads values from boot sequencer I2C
 ************************************************************************/
static long fixed_sdram(void)
{
	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
	u32 msizelog2, msize = 1;
#if defined(CONFIG_NAND_SPL)
	u32 i;
	const u8 bytecount = 135;
	u8 buffer[bytecount];
	u32 addr, data;

	si_read_i2c(0, bytecount, buffer);

	for (i = 18; i < bytecount; i += 7){
		addr = (u32)buffer[i];
		addr <<= 8;
		addr |= (u32)buffer[i + 1];
		addr <<= 2;
		data = (u32)buffer[i + 2];
		data <<= 8;
		data |= (u32)buffer[i + 3];
		data <<= 8;
		data |= (u32)buffer[i + 4];
		data <<= 8;
		data |= (u32)buffer[i + 5];

		__raw_writel(data, (u32 *)(CONFIG_SYS_IMMR + addr));
	}

	sync();

	/* enable DDR controller */
	__raw_writel((__raw_readl(&im->ddr.sdram_cfg) | SDRAM_CFG_MEM_EN), &im->ddr.sdram_cfg);
#endif /* (CONFIG_NAND_SPL) */

	msizelog2 = ((__raw_readl(&im->sysconf.ddrlaw[0].ar) & LAWAR_SIZE) + 1);
	msize <<= (msizelog2 - 20);

	return msize;
}