xref: /rk3399_rockchip-uboot/board/BuR/common/common.c (revision d804452bf4e4484d2ea305f3d4dc7ba219298fb3)
1 /*
2  * common.c
3  *
4  * common board functions for B&R boards
5  *
6  * Copyright (C) 2013 Hannes Petermaier <oe5hpm@oevsv.at>
7  * Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
8  *
9  * SPDX-License-Identifier:	GPL-2.0+
10  *
11  */
12 #include <version.h>
13 #include <common.h>
14 #include <errno.h>
15 #include <spl.h>
16 #include <asm/arch/cpu.h>
17 #include <asm/arch/hardware.h>
18 #include <asm/arch/omap.h>
19 #include <asm/arch/clock.h>
20 #include <asm/arch/gpio.h>
21 #include <asm/arch/sys_proto.h>
22 #include <asm/arch/mmc_host_def.h>
23 #include <asm/io.h>
24 #include <asm/gpio.h>
25 #include <i2c.h>
26 #include <miiphy.h>
27 #include <cpsw.h>
28 #include <power/tps65217.h>
29 #include <lcd.h>
30 #include <fs.h>
31 #ifdef CONFIG_USE_FDT
32   #include <fdt_support.h>
33 #endif
34 #include "bur_common.h"
35 #include "../../../drivers/video/am335x-fb.h"
36 #include <nand.h>
37 
38 static struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE;
39 
40 DECLARE_GLOBAL_DATA_PTR;
41 
42 #ifdef CONFIG_USE_FDT
43   #define FDTPROP(b, c) fdt_getprop_u32_default(gd->fdt_blob, b, c, ~0UL)
44   #define PATHTIM "/panel/display-timings/default"
45   #define PATHINF "/panel/panel-info"
46 #endif
47 /* --------------------------------------------------------------------------*/
48 #if defined(CONFIG_LCD) && defined(CONFIG_AM335X_LCD) && \
49 	!defined(CONFIG_SPL_BUILD)
50 int load_lcdtiming(struct am335x_lcdpanel *panel)
51 {
52 	struct am335x_lcdpanel pnltmp;
53 #ifdef CONFIG_USE_FDT
54 	u32 dtbprop;
55 	char buf[32];
56 	const char *nodep = 0;
57 	int nodeoff;
58 
59 	if (gd->fdt_blob == NULL) {
60 		printf("%s: don't have a valid gd->fdt_blob!\n", __func__);
61 		return -1;
62 	}
63 	memcpy(&pnltmp, (void *)panel, sizeof(struct am335x_lcdpanel));
64 
65 	pnltmp.hactive = FDTPROP(PATHTIM, "hactive");
66 	pnltmp.vactive = FDTPROP(PATHTIM, "vactive");
67 	pnltmp.bpp = FDTPROP(PATHINF, "bpp");
68 	pnltmp.hfp = FDTPROP(PATHTIM, "hfront-porch");
69 	pnltmp.hbp = FDTPROP(PATHTIM, "hback-porch");
70 	pnltmp.hsw = FDTPROP(PATHTIM, "hsync-len");
71 	pnltmp.vfp = FDTPROP(PATHTIM, "vfront-porch");
72 	pnltmp.vbp = FDTPROP(PATHTIM, "vback-porch");
73 	pnltmp.vsw = FDTPROP(PATHTIM, "vsync-len");
74 	pnltmp.pup_delay = FDTPROP(PATHTIM, "pupdelay");
75 	pnltmp.pon_delay = FDTPROP(PATHTIM, "pondelay");
76 
77 	/* calc. proper clk-divisor */
78 	dtbprop = FDTPROP(PATHTIM, "clock-frequency");
79 	if (dtbprop != ~0UL)
80 		pnltmp.pxl_clk_div = 192000000 / dtbprop;
81 	else
82 		pnltmp.pxl_clk_div = ~0UL;
83 
84 	/* check polarity of control-signals */
85 	dtbprop = FDTPROP(PATHTIM, "hsync-active");
86 	if (dtbprop == 0)
87 		pnltmp.pol |= HSYNC_INVERT;
88 	dtbprop = FDTPROP(PATHTIM, "vsync-active");
89 	if (dtbprop == 0)
90 		pnltmp.pol |= VSYNC_INVERT;
91 	dtbprop = FDTPROP(PATHINF, "sync-ctrl");
92 	if (dtbprop == 1)
93 		pnltmp.pol |= HSVS_CONTROL;
94 	dtbprop = FDTPROP(PATHINF, "sync-edge");
95 	if (dtbprop == 1)
96 		pnltmp.pol |= HSVS_RISEFALL;
97 	dtbprop = FDTPROP(PATHTIM, "pixelclk-active");
98 	if (dtbprop == 0)
99 		pnltmp.pol |= PXCLK_INVERT;
100 	dtbprop = FDTPROP(PATHTIM, "de-active");
101 	if (dtbprop == 0)
102 		pnltmp.pol |= DE_INVERT;
103 
104 	nodeoff = fdt_path_offset(gd->fdt_blob, "/factory-settings");
105 	if (nodeoff >= 0) {
106 		nodep = fdt_getprop(gd->fdt_blob, nodeoff, "rotation", NULL);
107 		if (nodep != 0) {
108 			if (strcmp(nodep, "cw") == 0)
109 				panel_info.vl_rot = 1;
110 			else if (strcmp(nodep, "ud") == 0)
111 				panel_info.vl_rot = 2;
112 			else if (strcmp(nodep, "ccw") == 0)
113 				panel_info.vl_rot = 3;
114 			else
115 				panel_info.vl_rot = 0;
116 		}
117 	} else {
118 		puts("no 'factory-settings / rotation' in dtb!\n");
119 	}
120 	snprintf(buf, sizeof(buf), "fbcon=rotate:%d", panel_info.vl_rot);
121 	setenv("optargs_rot", buf);
122 #else
123 	pnltmp.hactive = getenv_ulong("ds1_hactive", 10, ~0UL);
124 	pnltmp.vactive = getenv_ulong("ds1_vactive", 10, ~0UL);
125 	pnltmp.bpp = getenv_ulong("ds1_bpp", 10, ~0UL);
126 	pnltmp.hfp = getenv_ulong("ds1_hfp", 10, ~0UL);
127 	pnltmp.hbp = getenv_ulong("ds1_hbp", 10, ~0UL);
128 	pnltmp.hsw = getenv_ulong("ds1_hsw", 10, ~0UL);
129 	pnltmp.vfp = getenv_ulong("ds1_vfp", 10, ~0UL);
130 	pnltmp.vbp = getenv_ulong("ds1_vbp", 10, ~0UL);
131 	pnltmp.vsw = getenv_ulong("ds1_vsw", 10, ~0UL);
132 	pnltmp.pxl_clk_div = getenv_ulong("ds1_pxlclkdiv", 10, ~0UL);
133 	pnltmp.pol = getenv_ulong("ds1_pol", 16, ~0UL);
134 	pnltmp.pup_delay = getenv_ulong("ds1_pupdelay", 10, ~0UL);
135 	pnltmp.pon_delay = getenv_ulong("ds1_tondelay", 10, ~0UL);
136 	panel_info.vl_rot = getenv_ulong("ds1_rotation", 10, 0);
137 #endif
138 	if (
139 	   ~0UL == (pnltmp.hactive) ||
140 	   ~0UL == (pnltmp.vactive) ||
141 	   ~0UL == (pnltmp.bpp) ||
142 	   ~0UL == (pnltmp.hfp) ||
143 	   ~0UL == (pnltmp.hbp) ||
144 	   ~0UL == (pnltmp.hsw) ||
145 	   ~0UL == (pnltmp.vfp) ||
146 	   ~0UL == (pnltmp.vbp) ||
147 	   ~0UL == (pnltmp.vsw) ||
148 	   ~0UL == (pnltmp.pxl_clk_div) ||
149 	   ~0UL == (pnltmp.pol) ||
150 	   ~0UL == (pnltmp.pup_delay) ||
151 	   ~0UL == (pnltmp.pon_delay)
152 	   ) {
153 		puts("lcd-settings in env/dtb incomplete!\n");
154 		printf("display-timings:\n"
155 			"================\n"
156 			"hactive: %d\n"
157 			"vactive: %d\n"
158 			"bpp    : %d\n"
159 			"hfp    : %d\n"
160 			"hbp    : %d\n"
161 			"hsw    : %d\n"
162 			"vfp    : %d\n"
163 			"vbp    : %d\n"
164 			"vsw    : %d\n"
165 			"pxlclk : %d\n"
166 			"pol    : 0x%08x\n"
167 			"pondly : %d\n",
168 			pnltmp.hactive, pnltmp.vactive, pnltmp.bpp,
169 			pnltmp.hfp, pnltmp.hbp, pnltmp.hsw,
170 			pnltmp.vfp, pnltmp.vbp, pnltmp.vsw,
171 			pnltmp.pxl_clk_div, pnltmp.pol, pnltmp.pon_delay);
172 
173 		return -1;
174 	}
175 	debug("lcd-settings in env complete, taking over.\n");
176 	memcpy((void *)panel,
177 	       (void *)&pnltmp,
178 	       sizeof(struct am335x_lcdpanel));
179 
180 	return 0;
181 }
182 
183 #ifdef CONFIG_USE_FDT
184 static int load_devicetree(void)
185 {
186 	int rc;
187 	loff_t dtbsize;
188 	u32 dtbaddr = getenv_ulong("dtbaddr", 16, 0UL);
189 
190 	if (dtbaddr == 0) {
191 		printf("%s: don't have a valid <dtbaddr> in env!\n", __func__);
192 		return -1;
193 	}
194 #ifdef CONFIG_NAND
195 	dtbsize = 0x20000;
196 	rc = nand_read_skip_bad(&nand_info[0], 0x40000, (size_t *)&dtbsize,
197 				NULL, 0x20000, (u_char *)dtbaddr);
198 #else
199 	char *dtbname = getenv("dtb");
200 	char *dtbdev = getenv("dtbdev");
201 	char *dtppart = getenv("dtbpart");
202 	if (!dtbdev || !dtbdev || !dtbname) {
203 		printf("%s: <dtbdev>/<dtbpart>/<dtb> missing.\n", __func__);
204 		return -1;
205 	}
206 
207 	if (fs_set_blk_dev(dtbdev, dtppart, FS_TYPE_EXT)) {
208 		puts("load_devicetree: set_blk_dev failed.\n");
209 		return -1;
210 	}
211 	rc = fs_read(dtbname, (u32)dtbaddr, 0, 0, &dtbsize);
212 #endif
213 	if (rc == 0) {
214 		gd->fdt_blob = (void *)dtbaddr;
215 		gd->fdt_size = dtbsize;
216 		debug("loaded %d bytes of dtb onto 0x%08x\n",
217 		      (u32)dtbsize, (u32)gd->fdt_blob);
218 		return dtbsize;
219 	}
220 
221 	printf("%s: load dtb failed!\n", __func__);
222 	return -1;
223 }
224 
225 static const char *dtbmacaddr(u32 ifno)
226 {
227 	int node, len;
228 	char enet[16];
229 	const char *mac;
230 	const char *path;
231 
232 	if (gd->fdt_blob == NULL) {
233 		printf("%s: don't have a valid gd->fdt_blob!\n", __func__);
234 		return NULL;
235 	}
236 
237 	node = fdt_path_offset(gd->fdt_blob, "/aliases");
238 	if (node < 0)
239 		return NULL;
240 
241 	sprintf(enet, "ethernet%d", ifno);
242 	path = fdt_getprop(gd->fdt_blob, node, enet, NULL);
243 	if (!path) {
244 		printf("no alias for %s\n", enet);
245 		return NULL;
246 	}
247 
248 	node = fdt_path_offset(gd->fdt_blob, path);
249 	mac = fdt_getprop(gd->fdt_blob, node, "mac-address", &len);
250 	if (mac && is_valid_ethaddr((u8 *)mac))
251 		return mac;
252 
253 	return NULL;
254 }
255 
256 static void br_summaryscreen_printdtb(char *prefix,
257 				       char *name,
258 				       char *suffix)
259 {
260 	char buf[32] = { 0 };
261 	const char *nodep = buf;
262 	char *mac = 0;
263 	int nodeoffset;
264 	int len;
265 
266 	if (gd->fdt_blob == NULL) {
267 		printf("%s: don't have a valid gd->fdt_blob!\n", __func__);
268 		return;
269 	}
270 
271 	if (strcmp(name, "brmac1") == 0) {
272 		mac = (char *)dtbmacaddr(0);
273 		if (mac)
274 			sprintf(buf, "%pM", mac);
275 	} else if (strcmp(name, "brmac2") == 0) {
276 		mac =  (char *)dtbmacaddr(1);
277 		if (mac)
278 			sprintf(buf, "%pM", mac);
279 	} else {
280 		nodeoffset = fdt_path_offset(gd->fdt_blob,
281 					     "/factory-settings");
282 		if (nodeoffset < 0) {
283 			puts("no 'factory-settings' in dtb!\n");
284 			return;
285 		}
286 		nodep = fdt_getprop(gd->fdt_blob, nodeoffset, name, &len);
287 	}
288 	if (nodep && strlen(nodep) > 1)
289 		lcd_printf("%s %s %s", prefix, nodep, suffix);
290 	else
291 		lcd_printf("\n");
292 }
293 int ft_board_setup(void *blob, bd_t *bd)
294 {
295 	int nodeoffset;
296 
297 	nodeoffset = fdt_path_offset(blob, "/factory-settings");
298 	if (nodeoffset < 0) {
299 		puts("set bootloader version 'factory-settings' not in dtb!\n");
300 		return -1;
301 	}
302 	if (fdt_setprop(blob, nodeoffset, "bl-version",
303 			PLAIN_VERSION, strlen(PLAIN_VERSION)) != 0) {
304 		puts("set bootloader version 'bl-version' prop. not in dtb!\n");
305 		return -1;
306 	}
307 	return 0;
308 }
309 #else
310 
311 static void br_summaryscreen_printenv(char *prefix,
312 				       char *name, char *altname,
313 				       char *suffix)
314 {
315 	char *envval = getenv(name);
316 	if (0 != envval) {
317 		lcd_printf("%s %s %s", prefix, envval, suffix);
318 	} else if (0 != altname) {
319 		envval = getenv(altname);
320 		if (0 != envval)
321 			lcd_printf("%s %s %s", prefix, envval, suffix);
322 	} else {
323 		lcd_printf("\n");
324 	}
325 }
326 #endif
327 void br_summaryscreen(void)
328 {
329 #ifdef CONFIG_USE_FDT
330 	br_summaryscreen_printdtb(" - B&R -", "order-no", "-\n");
331 	br_summaryscreen_printdtb(" Serial/Rev :", "serial-no", " /");
332 	br_summaryscreen_printdtb(" ", "hw-revision", "\n");
333 	br_summaryscreen_printdtb(" MAC (IF1)  :", "brmac1", "\n");
334 	br_summaryscreen_printdtb(" MAC (IF2)  :", "brmac2", "\n");
335 	lcd_puts(" Bootloader : " PLAIN_VERSION "\n");
336 	lcd_puts("\n");
337 #else
338 	br_summaryscreen_printenv(" - B&R -", "br_orderno", 0, "-\n");
339 	br_summaryscreen_printenv(" Serial/Rev :", "br_serial", 0, "\n");
340 	br_summaryscreen_printenv(" MAC (IF1)  :", "br_mac1", "ethaddr", "\n");
341 	br_summaryscreen_printenv(" MAC (IF2)  :", "br_mac2", 0, "\n");
342 	lcd_puts(" Bootloader : " PLAIN_VERSION "\n");
343 	lcd_puts("\n");
344 #endif
345 }
346 
347 void lcdpower(int on)
348 {
349 	u32 pin, swval, i;
350 #ifdef CONFIG_USE_FDT
351 	if (gd->fdt_blob == NULL) {
352 		printf("%s: don't have a valid gd->fdt_blob!\n", __func__);
353 		return;
354 	}
355 	pin = FDTPROP(PATHINF, "pwrpin");
356 #else
357 	pin = getenv_ulong("ds1_pwr", 16, ~0UL);
358 #endif
359 	if (pin == ~0UL) {
360 		puts("no pwrpin in dtb/env, cannot powerup display!\n");
361 		return;
362 	}
363 
364 	for (i = 0; i < 3; i++) {
365 		if (pin != 0) {
366 			swval = pin & 0x80 ? 0 : 1;
367 			if (on)
368 				gpio_direction_output(pin & 0x7F, swval);
369 			else
370 				gpio_direction_output(pin & 0x7F, !swval);
371 
372 			debug("switched pin %d to %d\n", pin & 0x7F, swval);
373 		}
374 		pin >>= 8;
375 	}
376 }
377 
378 vidinfo_t	panel_info = {
379 		.vl_col = 1366,	/*
380 				 * give full resolution for allocating enough
381 				 * memory
382 				 */
383 		.vl_row = 768,
384 		.vl_bpix = 5,
385 		.priv = 0
386 };
387 
388 void lcd_ctrl_init(void *lcdbase)
389 {
390 	struct am335x_lcdpanel lcd_panel;
391 #ifdef CONFIG_USE_FDT
392 	/* TODO: is there a better place to load the dtb ? */
393 	load_devicetree();
394 #endif
395 	memset(&lcd_panel, 0, sizeof(struct am335x_lcdpanel));
396 	if (load_lcdtiming(&lcd_panel) != 0)
397 		return;
398 
399 	lcd_panel.panel_power_ctrl = &lcdpower;
400 
401 	if (0 != am335xfb_init(&lcd_panel))
402 		printf("ERROR: failed to initialize video!");
403 	/*
404 	 * modifiy panel info to 'real' resolution, to operate correct with
405 	 * lcd-framework.
406 	 */
407 	panel_info.vl_col = lcd_panel.hactive;
408 	panel_info.vl_row = lcd_panel.vactive;
409 
410 	lcd_set_flush_dcache(1);
411 }
412 
413 void lcd_enable(void)
414 {
415 #ifdef CONFIG_USE_FDT
416 	if (gd->fdt_blob == NULL) {
417 		printf("%s: don't have a valid gd->fdt_blob!\n", __func__);
418 		return;
419 	}
420 	unsigned int driver = FDTPROP(PATHINF, "brightdrv");
421 	unsigned int bright = FDTPROP(PATHINF, "brightdef");
422 	unsigned int pwmfrq = FDTPROP(PATHINF, "brightfdim");
423 #else
424 	unsigned int driver = getenv_ulong("ds1_bright_drv", 16, 0UL);
425 	unsigned int bright = getenv_ulong("ds1_bright_def", 10, 50);
426 	unsigned int pwmfrq = getenv_ulong("ds1_pwmfreq", 10, ~0UL);
427 #endif
428 	unsigned int tmp;
429 	struct gptimer *const timerhw = (struct gptimer *)DM_TIMER6_BASE;
430 
431 	bright = bright != ~0UL ? bright : 50;
432 
433 	switch (driver) {
434 	case 0:	/* PMIC LED-Driver */
435 		/* brightness level */
436 		tps65217_reg_write(TPS65217_PROT_LEVEL_NONE,
437 				   TPS65217_WLEDCTRL2, bright, 0xFF);
438 		/* turn on light */
439 		tps65217_reg_write(TPS65217_PROT_LEVEL_NONE,
440 				   TPS65217_WLEDCTRL1, 0x0A, 0xFF);
441 		break;
442 	case 1: /* PWM using timer6 */
443 		if (pwmfrq != ~0UL) {
444 			timerhw->tiocp_cfg = TCFG_RESET;
445 			udelay(10);
446 			while (timerhw->tiocp_cfg & TCFG_RESET)
447 				;
448 			tmp = ~0UL-(V_OSCK/pwmfrq);	/* bottom value */
449 			timerhw->tldr = tmp;
450 			timerhw->tcrr = tmp;
451 			tmp = tmp + ((V_OSCK/pwmfrq)/100) * bright;
452 			timerhw->tmar = tmp;
453 			timerhw->tclr = (TCLR_PT | (2 << TCLR_TRG_SHIFT) |
454 					TCLR_CE | TCLR_AR | TCLR_ST);
455 		} else {
456 			puts("invalid pwmfrq in env/dtb! skip PWM-setup.\n");
457 		}
458 		break;
459 	default:
460 		puts("no suitable backlightdriver in env/dtb!\n");
461 		break;
462 	}
463 	br_summaryscreen();
464 }
465 #elif CONFIG_SPL_BUILD
466 #else
467 #error "LCD-support with a suitable FB-Driver is mandatory !"
468 #endif /* CONFIG_LCD */
469 
470 #ifdef CONFIG_SPL_BUILD
471 void pmicsetup(u32 mpupll)
472 {
473 	int mpu_vdd;
474 	int usb_cur_lim;
475 
476 	if (i2c_probe(TPS65217_CHIP_PM)) {
477 		puts("PMIC (0x24) not found! skip further initalization.\n");
478 		return;
479 	}
480 
481 	/* Get the frequency which is defined by device fuses */
482 	dpll_mpu_opp100.m = am335x_get_efuse_mpu_max_freq(cdev);
483 	printf("detected max. frequency: %d - ", dpll_mpu_opp100.m);
484 
485 	if (0 != mpupll) {
486 		dpll_mpu_opp100.m = MPUPLL_M_1000;
487 		printf("retuning MPU-PLL to: %d MHz.\n", dpll_mpu_opp100.m);
488 	} else {
489 		puts("ok.\n");
490 	}
491 	/*
492 	 * Increase USB current limit to 1300mA or 1800mA and set
493 	 * the MPU voltage controller as needed.
494 	 */
495 	if (dpll_mpu_opp100.m == MPUPLL_M_1000) {
496 		usb_cur_lim = TPS65217_USB_INPUT_CUR_LIMIT_1800MA;
497 		mpu_vdd = TPS65217_DCDC_VOLT_SEL_1325MV;
498 	} else {
499 		usb_cur_lim = TPS65217_USB_INPUT_CUR_LIMIT_1300MA;
500 		mpu_vdd = TPS65217_DCDC_VOLT_SEL_1275MV;
501 	}
502 
503 	if (tps65217_reg_write(TPS65217_PROT_LEVEL_NONE, TPS65217_POWER_PATH,
504 			       usb_cur_lim, TPS65217_USB_INPUT_CUR_LIMIT_MASK))
505 		puts("tps65217_reg_write failure\n");
506 
507 	/* Set DCDC3 (CORE) voltage to 1.125V */
508 	if (tps65217_voltage_update(TPS65217_DEFDCDC3,
509 				    TPS65217_DCDC_VOLT_SEL_1125MV)) {
510 		puts("tps65217_voltage_update failure\n");
511 		return;
512 	}
513 
514 	/* Set CORE Frequencies to OPP100 */
515 	do_setup_dpll(&dpll_core_regs, &dpll_core_opp100);
516 
517 	/* Set DCDC2 (MPU) voltage */
518 	if (tps65217_voltage_update(TPS65217_DEFDCDC2, mpu_vdd)) {
519 		puts("tps65217_voltage_update failure\n");
520 		return;
521 	}
522 
523 	/* Set LDO3 to 1.8V */
524 	if (tps65217_reg_write(TPS65217_PROT_LEVEL_2,
525 			       TPS65217_DEFLS1,
526 			       TPS65217_LDO_VOLTAGE_OUT_1_8,
527 			       TPS65217_LDO_MASK))
528 		puts("tps65217_reg_write failure\n");
529 	/* Set LDO4 to 3.3V */
530 	if (tps65217_reg_write(TPS65217_PROT_LEVEL_2,
531 			       TPS65217_DEFLS2,
532 			       TPS65217_LDO_VOLTAGE_OUT_3_3,
533 			       TPS65217_LDO_MASK))
534 		puts("tps65217_reg_write failure\n");
535 
536 	/* Set MPU Frequency to what we detected now that voltages are set */
537 	do_setup_dpll(&dpll_mpu_regs, &dpll_mpu_opp100);
538 	/* Set PWR_EN bit in Status Register */
539 	tps65217_reg_write(TPS65217_PROT_LEVEL_NONE,
540 			   TPS65217_STATUS, TPS65217_PWR_OFF, TPS65217_PWR_OFF);
541 }
542 
543 void set_uart_mux_conf(void)
544 {
545 	enable_uart0_pin_mux();
546 }
547 
548 void set_mux_conf_regs(void)
549 {
550 	enable_board_pin_mux();
551 }
552 
553 #endif /* CONFIG_SPL_BUILD */
554 
555 #if (defined(CONFIG_DRIVER_TI_CPSW) && !defined(CONFIG_SPL_BUILD)) || \
556 	(defined(CONFIG_SPL_ETH_SUPPORT) && defined(CONFIG_SPL_BUILD))
557 static void cpsw_control(int enabled)
558 {
559 	/* VTP can be added here */
560 	return;
561 }
562 
563 /* describing port offsets of TI's CPSW block */
564 static struct cpsw_slave_data cpsw_slaves[] = {
565 	{
566 		.slave_reg_ofs	= 0x208,
567 		.sliver_reg_ofs	= 0xd80,
568 		.phy_addr	= 1,
569 	},
570 	{
571 		.slave_reg_ofs	= 0x308,
572 		.sliver_reg_ofs	= 0xdc0,
573 		.phy_addr	= 2,
574 	},
575 };
576 
577 static struct cpsw_platform_data cpsw_data = {
578 	.mdio_base		= CPSW_MDIO_BASE,
579 	.cpsw_base		= CPSW_BASE,
580 	.mdio_div		= 0xff,
581 	.channels		= 8,
582 	.cpdma_reg_ofs		= 0x800,
583 	.slaves			= 1,
584 	.slave_data		= cpsw_slaves,
585 	.ale_reg_ofs		= 0xd00,
586 	.ale_entries		= 1024,
587 	.host_port_reg_ofs	= 0x108,
588 	.hw_stats_reg_ofs	= 0x900,
589 	.bd_ram_ofs		= 0x2000,
590 	.mac_control		= (1 << 5),
591 	.control		= cpsw_control,
592 	.host_port_num		= 0,
593 	.version		= CPSW_CTRL_VERSION_2,
594 };
595 #endif /* CONFIG_DRIVER_TI_CPSW, ... */
596 
597 #if defined(CONFIG_DRIVER_TI_CPSW)
598 
599 int board_eth_init(bd_t *bis)
600 {
601 	int rv = 0;
602 	char mac_addr[6];
603 	const char *mac = 0;
604 	uint32_t mac_hi, mac_lo;
605 	/* try reading mac address from efuse */
606 	mac_lo = readl(&cdev->macid0l);
607 	mac_hi = readl(&cdev->macid0h);
608 	mac_addr[0] = mac_hi & 0xFF;
609 	mac_addr[1] = (mac_hi & 0xFF00) >> 8;
610 	mac_addr[2] = (mac_hi & 0xFF0000) >> 16;
611 	mac_addr[3] = (mac_hi & 0xFF000000) >> 24;
612 	mac_addr[4] = mac_lo & 0xFF;
613 	mac_addr[5] = (mac_lo & 0xFF00) >> 8;
614 
615 #if (defined(CONFIG_DRIVER_TI_CPSW) && !defined(CONFIG_SPL_BUILD)) || \
616 	(defined(CONFIG_SPL_ETH_SUPPORT) && defined(CONFIG_SPL_BUILD))
617 	if (!getenv("ethaddr")) {
618 		#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_USE_FDT)
619 		printf("<ethaddr> not set. trying DTB ... ");
620 		mac = dtbmacaddr(0);
621 		#endif
622 		if (!mac) {
623 			printf("<ethaddr> not set. validating E-fuse MAC ... ");
624 			if (is_valid_ethaddr((const u8 *)mac_addr))
625 				mac = (const char *)mac_addr;
626 		}
627 
628 		if (mac) {
629 			printf("using: %pM on ", mac);
630 			eth_setenv_enetaddr("ethaddr", (const u8 *)mac);
631 		}
632 	}
633 	writel(MII_MODE_ENABLE, &cdev->miisel);
634 	cpsw_slaves[0].phy_if = PHY_INTERFACE_MODE_MII;
635 	cpsw_slaves[1].phy_if =	PHY_INTERFACE_MODE_MII;
636 
637 	rv = cpsw_register(&cpsw_data);
638 	if (rv < 0) {
639 		printf("Error %d registering CPSW switch\n", rv);
640 		return 0;
641 	}
642 #endif /* CONFIG_DRIVER_TI_CPSW, ... */
643 	return rv;
644 }
645 #endif /* CONFIG_DRIVER_TI_CPSW */
646 #if defined(CONFIG_GENERIC_MMC) && !defined(CONFIG_SPL_BUILD)
647 int board_mmc_init(bd_t *bis)
648 {
649 	return omap_mmc_init(1, 0, 0, -1, -1);
650 }
651 #endif
652 int overwrite_console(void)
653 {
654 	return 1;
655 }
656