xref: /openbmc/u-boot/board/siemens/rut/board.c (revision ac45bb16)
1 /*
2  * Board functions for TI AM335X based rut board
3  * (C) Copyright 2013 Siemens Schweiz AG
4  * (C) Heiko Schocher, DENX Software Engineering, hs@denx.de.
5  *
6  * Based on:
7  * u-boot:/board/ti/am335x/board.c
8  *
9  * Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/
10  *
11  * SPDX-License-Identifier:	GPL-2.0+
12  */
13 
14 #include <common.h>
15 #include <errno.h>
16 #include <spi.h>
17 #include <spl.h>
18 #include <asm/arch/cpu.h>
19 #include <asm/arch/hardware.h>
20 #include <asm/arch/omap.h>
21 #include <asm/arch/ddr_defs.h>
22 #include <asm/arch/clock.h>
23 #include <asm/arch/gpio.h>
24 #include <asm/arch/mmc_host_def.h>
25 #include <asm/arch/sys_proto.h>
26 #include <asm/io.h>
27 #include <asm/emif.h>
28 #include <asm/gpio.h>
29 #include <i2c.h>
30 #include <miiphy.h>
31 #include <cpsw.h>
32 #include <video.h>
33 #include <watchdog.h>
34 #include "board.h"
35 #include "../common/factoryset.h"
36 #include "../../../drivers/video/da8xx-fb.h"
37 
38 DECLARE_GLOBAL_DATA_PTR;
39 
40 /*
41  * Read header information from EEPROM into global structure.
42  */
43 static int read_eeprom(void)
44 {
45 	return 0;
46 }
47 
48 #ifdef CONFIG_SPL_BUILD
49 static void board_init_ddr(void)
50 {
51 struct emif_regs rut_ddr3_emif_reg_data = {
52 	.sdram_config = 0x61C04AB2,
53 	.sdram_tim1 = 0x0888A39B,
54 	.sdram_tim2 = 0x26337FDA,
55 	.sdram_tim3 = 0x501F830F,
56 	.emif_ddr_phy_ctlr_1 = 0x6,
57 	.zq_config = 0x50074BE4,
58 	.ref_ctrl = 0x93B,
59 };
60 
61 struct ddr_data rut_ddr3_data = {
62 	.datardsratio0 = 0x3b,
63 	.datawdsratio0 = 0x85,
64 	.datafwsratio0 = 0x100,
65 	.datawrsratio0 = 0xc1,
66 };
67 
68 struct cmd_control rut_ddr3_cmd_ctrl_data = {
69 	.cmd0csratio = 0x40,
70 	.cmd0iclkout = 1,
71 	.cmd1csratio = 0x40,
72 	.cmd1iclkout = 1,
73 	.cmd2csratio = 0x40,
74 	.cmd2iclkout = 1,
75 };
76 
77 	config_ddr(DDR_PLL_FREQ, RUT_IOCTRL_VAL, &rut_ddr3_data,
78 		   &rut_ddr3_cmd_ctrl_data, &rut_ddr3_emif_reg_data, 0);
79 }
80 
81 static int request_and_pulse_reset(int gpio, const char *name)
82 {
83 	int ret;
84 	const int delay_us = 2000; /* 2ms */
85 
86 	ret = gpio_request(gpio, name);
87 	if (ret < 0) {
88 		printf("%s: Unable to request %s\n", __func__, name);
89 		goto err;
90 	}
91 
92 	ret = gpio_direction_output(gpio, 0);
93 	if (ret < 0) {
94 		printf("%s: Unable to set %s  as output\n", __func__, name);
95 		goto err_free_gpio;
96 	}
97 
98 	udelay(delay_us);
99 
100 	gpio_set_value(gpio, 1);
101 
102 	return 0;
103 
104 err_free_gpio:
105 	gpio_free(gpio);
106 err:
107 	return ret;
108 }
109 
110 #define GPIO_TO_PIN(bank, gpio)		(32 * (bank) + (gpio))
111 #define ETH_PHY_RESET_GPIO		GPIO_TO_PIN(2, 18)
112 #define MAXTOUCH_RESET_GPIO		GPIO_TO_PIN(3, 18)
113 #define DISPLAY_RESET_GPIO		GPIO_TO_PIN(3, 19)
114 
115 #define REQUEST_AND_PULSE_RESET(N) \
116 		request_and_pulse_reset(N, #N);
117 
118 static void spl_siemens_board_init(void)
119 {
120 	REQUEST_AND_PULSE_RESET(ETH_PHY_RESET_GPIO);
121 	REQUEST_AND_PULSE_RESET(MAXTOUCH_RESET_GPIO);
122 	REQUEST_AND_PULSE_RESET(DISPLAY_RESET_GPIO);
123 }
124 #endif /* if def CONFIG_SPL_BUILD */
125 
126 #if defined(CONFIG_DRIVER_TI_CPSW)
127 static void cpsw_control(int enabled)
128 {
129 	/* VTP can be added here */
130 
131 	return;
132 }
133 
134 static struct cpsw_slave_data cpsw_slaves[] = {
135 	{
136 		.slave_reg_ofs	= 0x208,
137 		.sliver_reg_ofs	= 0xd80,
138 		.phy_id		= 1,
139 		.phy_if		= PHY_INTERFACE_MODE_RMII,
140 	},
141 	{
142 		.slave_reg_ofs	= 0x308,
143 		.sliver_reg_ofs	= 0xdc0,
144 		.phy_id		= 0,
145 		.phy_if		= PHY_INTERFACE_MODE_RMII,
146 	},
147 };
148 
149 static struct cpsw_platform_data cpsw_data = {
150 	.mdio_base		= CPSW_MDIO_BASE,
151 	.cpsw_base		= CPSW_BASE,
152 	.mdio_div		= 0xff,
153 	.channels		= 8,
154 	.cpdma_reg_ofs		= 0x800,
155 	.slaves			= 1,
156 	.slave_data		= cpsw_slaves,
157 	.ale_reg_ofs		= 0xd00,
158 	.ale_entries		= 1024,
159 	.host_port_reg_ofs	= 0x108,
160 	.hw_stats_reg_ofs	= 0x900,
161 	.bd_ram_ofs		= 0x2000,
162 	.mac_control		= (1 << 5),
163 	.control		= cpsw_control,
164 	.host_port_num		= 0,
165 	.version		= CPSW_CTRL_VERSION_2,
166 };
167 
168 #if defined(CONFIG_DRIVER_TI_CPSW) || \
169 	(defined(CONFIG_USB_ETHER) && defined(CONFIG_MUSB_GADGET))
170 int board_eth_init(bd_t *bis)
171 {
172 	struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE;
173 	int n = 0;
174 	int rv;
175 
176 #ifndef CONFIG_SPL_BUILD
177 	factoryset_setenv();
178 #endif
179 
180 	/* Set rgmii mode and enable rmii clock to be sourced from chip */
181 	writel((RMII_MODE_ENABLE | RMII_CHIPCKL_ENABLE), &cdev->miisel);
182 
183 	rv = cpsw_register(&cpsw_data);
184 	if (rv < 0)
185 		printf("Error %d registering CPSW switch\n", rv);
186 	else
187 		n += rv;
188 	return n;
189 }
190 #endif /* #if defined(CONFIG_DRIVER_TI_CPSW) */
191 #endif /* #if (defined(CONFIG_DRIVER_TI_CPSW) && !defined(CONFIG_SPL_BUILD)) */
192 
193 #if defined(CONFIG_HW_WATCHDOG)
194 static bool hw_watchdog_init_done;
195 static int  hw_watchdog_trigger_level;
196 
197 void hw_watchdog_reset(void)
198 {
199 	if (!hw_watchdog_init_done)
200 		return;
201 
202 	hw_watchdog_trigger_level = hw_watchdog_trigger_level ? 0 : 1;
203 	gpio_set_value(WATCHDOG_TRIGGER_GPIO, hw_watchdog_trigger_level);
204 }
205 
206 void hw_watchdog_init(void)
207 {
208 	gpio_request(WATCHDOG_TRIGGER_GPIO, "watchdog_trigger");
209 	gpio_direction_output(WATCHDOG_TRIGGER_GPIO, hw_watchdog_trigger_level);
210 
211 	hw_watchdog_reset();
212 
213 	hw_watchdog_init_done = 1;
214 }
215 #endif /* defined(CONFIG_HW_WATCHDOG) */
216 
217 #if defined(CONFIG_VIDEO) && !defined(CONFIG_SPL_BUILD)
218 static struct da8xx_panel lcd_panels[] = {
219 	/* FORMIKE, 4.3", 480x800, KWH043MC17-F01 */
220 	[0] = {
221 		.name   = "KWH043MC17-F01",
222 		.width  = 480,
223 		.height = 800,
224 		.hfp = 50,              /* no spec, "don't care" values */
225 		.hbp = 50,
226 		.hsw = 50,
227 		.vfp = 50,
228 		.vbp = 50,
229 		.vsw = 50,
230 		.pxl_clk = 35910000,    /* tCYCD=20ns, max 50MHz, 60fps */
231 		.invert_pxl_clk = 1,
232 	},
233 	/* FORMIKE, 4.3", 480x800, KWH043ST20-F01 */
234 	[1] = {
235 		.name   = "KWH043ST20-F01",
236 		.width  = 480,
237 		.height = 800,
238 		.hfp = 50,              /* no spec, "don't care" values */
239 		.hbp = 50,
240 		.hsw = 50,
241 		.vfp = 50,
242 		.vbp = 50,
243 		.vsw = 50,
244 		.pxl_clk = 35910000,    /* tCYCD=20ns, max 50MHz, 60fps */
245 		.invert_pxl_clk = 1,
246 	},
247 	/* Multi-Inno, 4.3", 480x800, MI0430VT-1 */
248 	[2] = {
249 		.name   = "MI0430VT-1",
250 		.width  = 480,
251 		.height = 800,
252 		.hfp = 50,              /* no spec, "don't care" values */
253 		.hbp = 50,
254 		.hsw = 50,
255 		.vfp = 50,
256 		.vbp = 50,
257 		.vsw = 50,
258 		.pxl_clk = 35910000,    /* tCYCD=20ns, max 50MHz, 60fps */
259 		.invert_pxl_clk = 1,
260 	},
261 };
262 
263 static const struct display_panel disp_panels[] = {
264 	[0] = {
265 		WVGA,
266 		16,	/* RGB 888 */
267 		16,
268 		COLOR_ACTIVE,
269 	},
270 	[1] = {
271 		WVGA,
272 		16,	/* RGB 888 */
273 		16,
274 		COLOR_ACTIVE,
275 	},
276 	[2] = {
277 		WVGA,
278 		24,	/* RGB 888 */
279 		16,
280 		COLOR_ACTIVE,
281 	},
282 };
283 
284 static const struct lcd_ctrl_config lcd_cfgs[] = {
285 	[0] = {
286 		&disp_panels[0],
287 		.ac_bias		= 255,
288 		.ac_bias_intrpt		= 0,
289 		.dma_burst_sz		= 16,
290 		.bpp			= 16,
291 		.fdd			= 0x80,
292 		.tft_alt_mode		= 0,
293 		.stn_565_mode		= 0,
294 		.mono_8bit_mode		= 0,
295 		.invert_line_clock	= 1,
296 		.invert_frm_clock	= 1,
297 		.sync_edge		= 0,
298 		.sync_ctrl		= 1,
299 		.raster_order		= 0,
300 	},
301 	[1] = {
302 		&disp_panels[1],
303 		.ac_bias		= 255,
304 		.ac_bias_intrpt		= 0,
305 		.dma_burst_sz		= 16,
306 		.bpp			= 16,
307 		.fdd			= 0x80,
308 		.tft_alt_mode		= 0,
309 		.stn_565_mode		= 0,
310 		.mono_8bit_mode		= 0,
311 		.invert_line_clock	= 1,
312 		.invert_frm_clock	= 1,
313 		.sync_edge		= 0,
314 		.sync_ctrl		= 1,
315 		.raster_order		= 0,
316 	},
317 	[2] = {
318 		&disp_panels[2],
319 		.ac_bias		= 255,
320 		.ac_bias_intrpt		= 0,
321 		.dma_burst_sz		= 16,
322 		.bpp			= 24,
323 		.fdd			= 0x80,
324 		.tft_alt_mode		= 0,
325 		.stn_565_mode		= 0,
326 		.mono_8bit_mode		= 0,
327 		.invert_line_clock	= 1,
328 		.invert_frm_clock	= 1,
329 		.sync_edge		= 0,
330 		.sync_ctrl		= 1,
331 		.raster_order		= 0,
332 	},
333 
334 };
335 
336 /* no console on this board */
337 int board_cfb_skip(void)
338 {
339 	return 1;
340 }
341 
342 #define PLL_GET_M(v) ((v >> 8) & 0x7ff)
343 #define PLL_GET_N(v) (v & 0x7f)
344 
345 static struct dpll_regs dpll_lcd_regs = {
346 	.cm_clkmode_dpll = CM_WKUP + 0x98,
347 	.cm_idlest_dpll = CM_WKUP + 0x48,
348 	.cm_clksel_dpll = CM_WKUP + 0x54,
349 };
350 
351 static int get_clk(struct dpll_regs *dpll_regs)
352 {
353 	unsigned int val;
354 	unsigned int m, n;
355 	int f = 0;
356 
357 	val = readl(dpll_regs->cm_clksel_dpll);
358 	m = PLL_GET_M(val);
359 	n = PLL_GET_N(val);
360 	f = (m * V_OSCK) / n;
361 
362 	return f;
363 };
364 
365 int clk_get(int clk)
366 {
367 	return get_clk(&dpll_lcd_regs);
368 };
369 
370 static int conf_disp_pll(int m, int n)
371 {
372 	struct cm_perpll *cmper = (struct cm_perpll *)CM_PER;
373 	struct dpll_params dpll_lcd = {m, n, -1, -1, -1, -1, -1};
374 #if defined(DISPL_PLL_SPREAD_SPECTRUM)
375 	struct cm_wkuppll *cmwkup = (struct cm_wkuppll *)CM_WKUP;
376 #endif
377 
378 	u32 *const clk_domains[] = {
379 		&cmper->lcdclkctrl,
380 		0
381 	};
382 	u32 *const clk_modules_explicit_en[] = {
383 		&cmper->lcdclkctrl,
384 		&cmper->lcdcclkstctrl,
385 		&cmper->spi1clkctrl,
386 		0
387 	};
388 	do_enable_clocks(clk_domains, clk_modules_explicit_en, 1);
389 
390 	do_setup_dpll(&dpll_lcd_regs, &dpll_lcd);
391 
392 #if defined(DISPL_PLL_SPREAD_SPECTRUM)
393 	writel(0x64, &cmwkup->resv6[3]); /* 0x50 */
394 	writel(0x800, &cmwkup->resv6[2]); /* 0x4c */
395 	writel(readl(&cmwkup->clkmoddplldisp) | (1 << 12),
396 	       &cmwkup->clkmoddplldisp); /* 0x98 */
397 #endif
398 	return 0;
399 }
400 
401 static int set_gpio(int gpio, int state)
402 {
403 	gpio_request(gpio, "temp");
404 	gpio_direction_output(gpio, state);
405 	gpio_set_value(gpio, state);
406 	gpio_free(gpio);
407 	return 0;
408 }
409 
410 static int enable_lcd(void)
411 {
412 	unsigned char buf[1];
413 
414 	set_gpio(BOARD_LCD_RESET, 0);
415 	mdelay(1);
416 	set_gpio(BOARD_LCD_RESET, 1);
417 	mdelay(1);
418 
419 	/* spi lcd init */
420 	kwh043st20_f01_spi_startup(1, 0, 5000000, SPI_MODE_0);
421 
422 	/* backlight on */
423 	buf[0] = 0xf;
424 	i2c_write(0x24, 0x7, 1, buf, 1);
425 	buf[0] = 0x3f;
426 	i2c_write(0x24, 0x8, 1, buf, 1);
427 	return 0;
428 }
429 
430 int arch_early_init_r(void)
431 {
432 	enable_lcd();
433 	return 0;
434 }
435 
436 static int board_video_init(void)
437 {
438 	int i;
439 	int anzdisp = ARRAY_SIZE(lcd_panels);
440 	int display = 1;
441 
442 	for (i = 0; i < anzdisp; i++) {
443 		if (strncmp((const char *)factory_dat.disp_name,
444 			    lcd_panels[i].name,
445 		    strlen((const char *)factory_dat.disp_name)) == 0) {
446 			printf("DISPLAY: %s\n", factory_dat.disp_name);
447 			break;
448 		}
449 	}
450 	if (i == anzdisp) {
451 		i = 1;
452 		printf("%s: %s not found, using default %s\n", __func__,
453 		       factory_dat.disp_name, lcd_panels[i].name);
454 	}
455 	conf_disp_pll(24, 1);
456 	da8xx_video_init(&lcd_panels[display], &lcd_cfgs[display],
457 			 lcd_cfgs[display].bpp);
458 
459 	return 0;
460 }
461 #endif /* ifdef CONFIG_VIDEO */
462 #include "../common/board.c"
463