1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * CI20 setup code
4 *
5 * Copyright (c) 2013 Imagination Technologies
6 * Author: Paul Burton <paul.burton@imgtec.com>
7 */
8
9#include <common.h>
10#include <env.h>
11#include <init.h>
12#include <net.h>
13#include <netdev.h>
14#include <asm/global_data.h>
15#include <asm/io.h>
16#include <asm/gpio.h>
17#include <linux/bitops.h>
18#include <linux/delay.h>
19#include <mach/jz4780.h>
20#include <mach/jz4780_dram.h>
21#include <mach/jz4780_gpio.h>
22
23struct ci20_otp {
24	u32	serial_number;
25	u32	date;
26	u8	manufacturer[2];
27	u8	mac[6];
28} __packed;
29
30static void ci20_mux_mmc(void)
31{
32	void __iomem *gpio_regs = (void __iomem *)GPIO_BASE;
33
34	/* setup MSC1 pins */
35	writel(0x30f00000, gpio_regs + GPIO_PXINTC(4));
36	writel(0x30f00000, gpio_regs + GPIO_PXMASKC(4));
37	writel(0x30f00000, gpio_regs + GPIO_PXPAT1C(4));
38	writel(0x30f00000, gpio_regs + GPIO_PXPAT0C(4));
39	writel(0x30f00000, gpio_regs + GPIO_PXPENC(4));
40	jz4780_clk_ungate_mmc();
41}
42
43#ifndef CONFIG_SPL_BUILD
44
45static void ci20_mux_eth(void)
46{
47	void __iomem *gpio_regs = (void __iomem *)GPIO_BASE;
48
49#ifdef CONFIG_MTD_RAW_NAND
50	/* setup pins (some already setup for NAND) */
51	writel(0x04030000, gpio_regs + GPIO_PXINTC(0));
52	writel(0x04030000, gpio_regs + GPIO_PXMASKC(0));
53	writel(0x04030000, gpio_regs + GPIO_PXPAT1C(0));
54	writel(0x04030000, gpio_regs + GPIO_PXPAT0C(0));
55	writel(0x04030000, gpio_regs + GPIO_PXPENS(0));
56#else
57	/* setup pins (as above +NAND CS +RD/WE +SDx +SAx) */
58	writel(0x0dff00ff, gpio_regs + GPIO_PXINTC(0));
59	writel(0x0dff00ff, gpio_regs + GPIO_PXMASKC(0));
60	writel(0x0dff00ff, gpio_regs + GPIO_PXPAT1C(0));
61	writel(0x0dff00ff, gpio_regs + GPIO_PXPAT0C(0));
62	writel(0x0dff00ff, gpio_regs + GPIO_PXPENS(0));
63	writel(0x00000003, gpio_regs + GPIO_PXINTC(1));
64	writel(0x00000003, gpio_regs + GPIO_PXMASKC(1));
65	writel(0x00000003, gpio_regs + GPIO_PXPAT1C(1));
66	writel(0x00000003, gpio_regs + GPIO_PXPAT0C(1));
67	writel(0x00000003, gpio_regs + GPIO_PXPENS(1));
68#endif
69}
70
71static void ci20_mux_jtag(void)
72{
73#ifdef CONFIG_JTAG
74	void __iomem *gpio_regs = (void __iomem *)GPIO_BASE;
75
76	/* enable JTAG */
77	writel(3 << 30, gpio_regs + GPIO_PXINTC(0));
78	writel(3 << 30, gpio_regs + GPIO_PXMASKC(0));
79	writel(3 << 30, gpio_regs + GPIO_PXPAT1C(0));
80	writel(3 << 30, gpio_regs + GPIO_PXPAT0C(0));
81#endif
82}
83
84static void ci20_mux_nand(void)
85{
86	void __iomem *gpio_regs = (void __iomem *)GPIO_BASE;
87
88	/* setup pins */
89	writel(0x002c00ff, gpio_regs + GPIO_PXINTC(0));
90	writel(0x002c00ff, gpio_regs + GPIO_PXMASKC(0));
91	writel(0x002c00ff, gpio_regs + GPIO_PXPAT1C(0));
92	writel(0x002c00ff, gpio_regs + GPIO_PXPAT0C(0));
93	writel(0x002c00ff, gpio_regs + GPIO_PXPENS(0));
94	writel(0x00000003, gpio_regs + GPIO_PXINTC(1));
95	writel(0x00000003, gpio_regs + GPIO_PXMASKC(1));
96	writel(0x00000003, gpio_regs + GPIO_PXPAT1C(1));
97	writel(0x00000003, gpio_regs + GPIO_PXPAT0C(1));
98	writel(0x00000003, gpio_regs + GPIO_PXPENS(1));
99
100	/* FRB0_N */
101	jz47xx_gpio_direction_input(JZ_GPIO(0, 20));
102	writel(20, gpio_regs + GPIO_PXPENS(0));
103
104	/* disable write protect */
105	jz47xx_gpio_direction_output(JZ_GPIO(5, 22), 1);
106}
107
108static void ci20_mux_uart(void)
109{
110	void __iomem *gpio_regs = (void __iomem *)GPIO_BASE;
111
112	/* UART0 */
113	writel(0x9, gpio_regs + GPIO_PXINTC(5));
114	writel(0x9, gpio_regs + GPIO_PXMASKC(5));
115	writel(0x9, gpio_regs + GPIO_PXPAT1C(5));
116	writel(0x9, gpio_regs + GPIO_PXPAT0C(5));
117	writel(0x9, gpio_regs + GPIO_PXPENC(5));
118	jz4780_clk_ungate_uart(0);
119
120	/* UART 1 and 2 */
121	jz4780_clk_ungate_uart(1);
122	jz4780_clk_ungate_uart(2);
123
124#ifndef CONFIG_JTAG
125	/* UART3 */
126	writel(1 << 12, gpio_regs + GPIO_PXINTC(3));
127	writel(1 << 12, gpio_regs + GPIO_PXMASKS(3));
128	writel(1 << 12, gpio_regs + GPIO_PXPAT1S(3));
129	writel(1 << 12, gpio_regs + GPIO_PXPAT0C(3));
130	writel(3 << 30, gpio_regs + GPIO_PXINTC(0));
131	writel(3 << 30, gpio_regs + GPIO_PXMASKC(0));
132	writel(3 << 30, gpio_regs + GPIO_PXPAT1C(0));
133	writel(1 << 30, gpio_regs + GPIO_PXPAT0C(0));
134	writel(1 << 31, gpio_regs + GPIO_PXPAT0S(0));
135	jz4780_clk_ungate_uart(3);
136#endif
137
138	/* UART4 */
139	writel(0x100400, gpio_regs + GPIO_PXINTC(2));
140	writel(0x100400, gpio_regs + GPIO_PXMASKC(2));
141	writel(0x100400, gpio_regs + GPIO_PXPAT1S(2));
142	writel(0x100400, gpio_regs + GPIO_PXPAT0C(2));
143	writel(0x100400, gpio_regs + GPIO_PXPENC(2));
144	jz4780_clk_ungate_uart(4);
145}
146
147int board_early_init_f(void)
148{
149	ci20_mux_jtag();
150	ci20_mux_uart();
151
152	ci20_mux_eth();
153	ci20_mux_mmc();
154	ci20_mux_nand();
155
156	/* SYS_POWER_IND high (LED blue, VBUS off) */
157	jz47xx_gpio_direction_output(JZ_GPIO(5, 15), 0);
158
159	/* LEDs off */
160	jz47xx_gpio_direction_output(JZ_GPIO(2, 0), 0);
161	jz47xx_gpio_direction_output(JZ_GPIO(2, 1), 0);
162	jz47xx_gpio_direction_output(JZ_GPIO(2, 2), 0);
163	jz47xx_gpio_direction_output(JZ_GPIO(2, 3), 0);
164
165	return 0;
166}
167
168int misc_init_r(void)
169{
170	const u32 efuse_clk = jz4780_clk_get_efuse_clk();
171	struct ci20_otp otp;
172	char manufacturer[3];
173
174	/* Read the board OTP data */
175	jz4780_efuse_init(efuse_clk);
176	jz4780_efuse_read(0x18, 16, (u8 *)&otp);
177
178	/* Set MAC address */
179	if (!is_valid_ethaddr(otp.mac)) {
180		/* no MAC assigned, generate one from the unique chip ID */
181		jz4780_efuse_read(0x8, 4, &otp.mac[0]);
182		jz4780_efuse_read(0x12, 2, &otp.mac[4]);
183		otp.mac[0] = (otp.mac[0] | 0x02) & ~0x01;
184	}
185	eth_env_set_enetaddr("ethaddr", otp.mac);
186
187	/* Put other board information into the environment */
188	env_set_ulong("serial#", otp.serial_number);
189	env_set_ulong("board_date", otp.date);
190	manufacturer[0] = otp.manufacturer[0];
191	manufacturer[1] = otp.manufacturer[1];
192	manufacturer[2] = 0;
193	env_set("board_mfr", manufacturer);
194
195	return 0;
196}
197
198#ifdef CONFIG_DRIVER_DM9000
199int board_eth_init(struct bd_info *bis)
200{
201	/* Enable clock */
202	jz4780_clk_ungate_ethernet();
203
204	/* Enable power (PB25) */
205	jz47xx_gpio_direction_output(JZ_GPIO(1, 25), 1);
206
207	/* Reset (PF12) */
208	mdelay(10);
209	jz47xx_gpio_direction_output(JZ_GPIO(5, 12), 0);
210	mdelay(10);
211	jz47xx_gpio_direction_output(JZ_GPIO(5, 12), 1);
212	mdelay(10);
213
214	return dm9000_initialize(bis);
215}
216#endif /* CONFIG_DRIVER_DM9000 */
217#endif
218
219static u8 ci20_revision(void)
220{
221	void __iomem *gpio_regs = (void __iomem *)GPIO_BASE;
222	int val;
223
224	jz47xx_gpio_direction_input(JZ_GPIO(2, 18));
225	jz47xx_gpio_direction_input(JZ_GPIO(2, 19));
226
227	/* Enable pullups */
228	writel(BIT(18) | BIT(19), gpio_regs + GPIO_PXPENC(2));
229
230	/* Read PC18/19 for version */
231	val = (!!jz47xx_gpio_get_value(JZ_GPIO(2, 18))) |
232	     ((!!jz47xx_gpio_get_value(JZ_GPIO(2, 19))) << 1);
233
234	if (val == 3)	/* Rev 1 boards had no pulldowns - giving 3 */
235		return 1;
236	if (val == 1)	/* Rev 2 boards pulldown port C bit 18 giving 1 */
237		return 2;
238
239	return 0;
240}
241
242int dram_init(void)
243{
244	gd->ram_size = sdram_size(0) + sdram_size(1);
245	return 0;
246}
247
248/* U-Boot common routines */
249int checkboard(void)
250{
251	printf("Board: Creator CI20 (rev.%d)\n", ci20_revision());
252	return 0;
253}
254
255#ifdef CONFIG_SPL_BUILD
256
257#if defined(CONFIG_SPL_MMC)
258int board_mmc_init(struct bd_info *bd)
259{
260	ci20_mux_mmc();
261	return jz_mmc_init((void __iomem *)MSC0_BASE);
262}
263#endif
264
265static const struct jz4780_ddr_config K4B2G0846Q_48_config = {
266	.timing = {
267		(4 << DDRC_TIMING1_TRTP_BIT) | (13 << DDRC_TIMING1_TWTR_BIT) |
268		(6 << DDRC_TIMING1_TWR_BIT) | (5 << DDRC_TIMING1_TWL_BIT),
269
270		(4 << DDRC_TIMING2_TCCD_BIT) | (15 << DDRC_TIMING2_TRAS_BIT) |
271		(6 << DDRC_TIMING2_TRCD_BIT) | (6 << DDRC_TIMING2_TRL_BIT),
272
273		(4 << DDRC_TIMING3_ONUM) | (7 << DDRC_TIMING3_TCKSRE_BIT) |
274		(6 << DDRC_TIMING3_TRP_BIT) | (4 << DDRC_TIMING3_TRRD_BIT) |
275		(21 << DDRC_TIMING3_TRC_BIT),
276
277		(31 << DDRC_TIMING4_TRFC_BIT) | (1 << DDRC_TIMING4_TRWCOV_BIT) |
278		(4 << DDRC_TIMING4_TCKE_BIT) | (9 << DDRC_TIMING4_TMINSR_BIT) |
279		(8 << DDRC_TIMING4_TXP_BIT) | (3 << DDRC_TIMING4_TMRD_BIT),
280
281		(8 << DDRC_TIMING5_TRTW_BIT) | (4 << DDRC_TIMING5_TRDLAT_BIT) |
282		(4 << DDRC_TIMING5_TWDLAT_BIT),
283
284		(25 << DDRC_TIMING6_TXSRD_BIT) | (12 << DDRC_TIMING6_TFAW_BIT) |
285		(2 << DDRC_TIMING6_TCFGW_BIT) | (2 << DDRC_TIMING6_TCFGR_BIT),
286	},
287
288	/* PHY */
289	/* Mode Register 0 */
290	.mr0 = 0x420,
291#ifdef SDRAM_DISABLE_DLL
292	.mr1 = (DDR3_MR1_DIC_7 | DDR3_MR1_RTT_DIS | DDR3_MR1_DLL_DISABLE),
293#else
294	.mr1 = (DDR3_MR1_DIC_7 | DDR3_MR1_RTT_DIS),
295#endif
296
297	.ptr0 = 0x002000d4,
298	.ptr1 = 0x02230d40,
299	.ptr2 = 0x04013880,
300
301	.dtpr0 = 0x2a8f6690,
302	.dtpr1 = 0x00400860,
303	.dtpr2 = 0x10042a00,
304
305	.pullup = 0x0b,
306	.pulldn = 0x0b,
307};
308
309static const struct jz4780_ddr_config H5TQ2G83CFR_48_config = {
310	.timing = {
311		(4 << DDRC_TIMING1_TRTP_BIT) | (13 << DDRC_TIMING1_TWTR_BIT) |
312		(6 << DDRC_TIMING1_TWR_BIT) | (5 << DDRC_TIMING1_TWL_BIT),
313
314		(4 << DDRC_TIMING2_TCCD_BIT) | (16 << DDRC_TIMING2_TRAS_BIT) |
315		(6 << DDRC_TIMING2_TRCD_BIT) | (6 << DDRC_TIMING2_TRL_BIT),
316
317		(4 << DDRC_TIMING3_ONUM) | (7 << DDRC_TIMING3_TCKSRE_BIT) |
318		(6 << DDRC_TIMING3_TRP_BIT) | (4 << DDRC_TIMING3_TRRD_BIT) |
319		(22 << DDRC_TIMING3_TRC_BIT),
320
321		(42 << DDRC_TIMING4_TRFC_BIT) | (1 << DDRC_TIMING4_TRWCOV_BIT) |
322		(4 << DDRC_TIMING4_TCKE_BIT) | (7 << DDRC_TIMING4_TMINSR_BIT) |
323		(3 << DDRC_TIMING4_TXP_BIT) | (3 << DDRC_TIMING4_TMRD_BIT),
324
325		(8 << DDRC_TIMING5_TRTW_BIT) | (4 << DDRC_TIMING5_TRDLAT_BIT) |
326		(4 << DDRC_TIMING5_TWDLAT_BIT),
327
328		(25 << DDRC_TIMING6_TXSRD_BIT) | (20 << DDRC_TIMING6_TFAW_BIT) |
329		(2 << DDRC_TIMING6_TCFGW_BIT) | (2 << DDRC_TIMING6_TCFGR_BIT),
330	},
331
332	/* PHY */
333	/* Mode Register 0 */
334	.mr0 = 0x420,
335#ifdef SDRAM_DISABLE_DLL
336	.mr1 = (DDR3_MR1_DIC_7 | DDR3_MR1_RTT_DIS | DDR3_MR1_DLL_DISABLE),
337#else
338	.mr1 = (DDR3_MR1_DIC_7 | DDR3_MR1_RTT_DIS),
339#endif
340
341	.ptr0 = 0x002000d4,
342	.ptr1 = 0x02d30d40,
343	.ptr2 = 0x04013880,
344
345	.dtpr0 = 0x2c906690,
346	.dtpr1 = 0x005608a0,
347	.dtpr2 = 0x10042a00,
348
349	.pullup = 0x0e,
350	.pulldn = 0x0e,
351};
352
353const struct jz4780_ddr_config *jz4780_get_ddr_config(void)
354{
355	const int board_revision = ci20_revision();
356
357	if (board_revision == 2)
358		return &K4B2G0846Q_48_config;
359	else /* Fall back to H5TQ2G83CFR RAM */
360		return &H5TQ2G83CFR_48_config;
361}
362#endif
363