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