]>
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); | |
382bee57 | 187 | env_set("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; | |
573cc46c GS |
262 | rc = nand_read_skip_bad(get_nand_dev_by_index(0), 0x40000, |
263 | (size_t *)&dtbsize, | |
d79c138c HP |
264 | NULL, 0x20000, (u_char *)dtbaddr); |
265 | #else | |
00caae6d SG |
266 | char *dtbname = env_get("dtb"); |
267 | char *dtbdev = env_get("dtbdev"); | |
268 | char *dtbpart = env_get("dtbpart"); | |
169b50ef | 269 | if (!dtbdev || !dtbpart || !dtbname) { |
47c14227 | 270 | printf("%s: <dtbdev>/<dtbpart>/<dtb> missing.\n", __func__); |
fbd5aeda HP |
271 | return -1; |
272 | } | |
273 | ||
169b50ef | 274 | if (fs_set_blk_dev(dtbdev, dtbpart, FS_TYPE_EXT)) { |
fbd5aeda HP |
275 | puts("load_devicetree: set_blk_dev failed.\n"); |
276 | return -1; | |
277 | } | |
47c14227 | 278 | rc = fs_read(dtbname, (u32)dtbaddr, 0, 0, &dtbsize); |
d79c138c | 279 | #endif |
47c14227 HP |
280 | if (rc == 0) { |
281 | gd->fdt_blob = (void *)dtbaddr; | |
282 | gd->fdt_size = dtbsize; | |
283 | debug("loaded %d bytes of dtb onto 0x%08x\n", | |
284 | (u32)dtbsize, (u32)gd->fdt_blob); | |
285 | return dtbsize; | |
fbd5aeda HP |
286 | } |
287 | ||
47c14227 | 288 | printf("%s: load dtb failed!\n", __func__); |
fbd5aeda HP |
289 | return -1; |
290 | } | |
291 | ||
292 | static const char *dtbmacaddr(u32 ifno) | |
293 | { | |
294 | int node, len; | |
295 | char enet[16]; | |
296 | const char *mac; | |
297 | const char *path; | |
fbd5aeda | 298 | |
47c14227 HP |
299 | if (gd->fdt_blob == NULL) { |
300 | printf("%s: don't have a valid gd->fdt_blob!\n", __func__); | |
fbd5aeda HP |
301 | return NULL; |
302 | } | |
303 | ||
47c14227 | 304 | node = fdt_path_offset(gd->fdt_blob, "/aliases"); |
fbd5aeda HP |
305 | if (node < 0) |
306 | return NULL; | |
307 | ||
308 | sprintf(enet, "ethernet%d", ifno); | |
47c14227 | 309 | path = fdt_getprop(gd->fdt_blob, node, enet, NULL); |
fbd5aeda HP |
310 | if (!path) { |
311 | printf("no alias for %s\n", enet); | |
312 | return NULL; | |
313 | } | |
314 | ||
47c14227 HP |
315 | node = fdt_path_offset(gd->fdt_blob, path); |
316 | mac = fdt_getprop(gd->fdt_blob, node, "mac-address", &len); | |
0adb5b76 | 317 | if (mac && is_valid_ethaddr((u8 *)mac)) |
fbd5aeda HP |
318 | return mac; |
319 | ||
320 | return NULL; | |
321 | } | |
322 | ||
323 | static void br_summaryscreen_printdtb(char *prefix, | |
324 | char *name, | |
325 | char *suffix) | |
326 | { | |
fbd5aeda HP |
327 | char buf[32] = { 0 }; |
328 | const char *nodep = buf; | |
329 | char *mac = 0; | |
330 | int nodeoffset; | |
331 | int len; | |
332 | ||
47c14227 HP |
333 | if (gd->fdt_blob == NULL) { |
334 | printf("%s: don't have a valid gd->fdt_blob!\n", __func__); | |
fbd5aeda HP |
335 | return; |
336 | } | |
337 | ||
338 | if (strcmp(name, "brmac1") == 0) { | |
339 | mac = (char *)dtbmacaddr(0); | |
340 | if (mac) | |
341 | sprintf(buf, "%pM", mac); | |
342 | } else if (strcmp(name, "brmac2") == 0) { | |
343 | mac = (char *)dtbmacaddr(1); | |
344 | if (mac) | |
345 | sprintf(buf, "%pM", mac); | |
346 | } else { | |
47c14227 | 347 | nodeoffset = fdt_path_offset(gd->fdt_blob, |
fbd5aeda HP |
348 | "/factory-settings"); |
349 | if (nodeoffset < 0) { | |
350 | puts("no 'factory-settings' in dtb!\n"); | |
351 | return; | |
352 | } | |
47c14227 | 353 | nodep = fdt_getprop(gd->fdt_blob, nodeoffset, name, &len); |
fbd5aeda HP |
354 | } |
355 | if (nodep && strlen(nodep) > 1) | |
356 | lcd_printf("%s %s %s", prefix, nodep, suffix); | |
357 | else | |
358 | lcd_printf("\n"); | |
359 | } | |
360 | int ft_board_setup(void *blob, bd_t *bd) | |
361 | { | |
362 | int nodeoffset; | |
363 | ||
364 | nodeoffset = fdt_path_offset(blob, "/factory-settings"); | |
365 | if (nodeoffset < 0) { | |
366 | puts("set bootloader version 'factory-settings' not in dtb!\n"); | |
367 | return -1; | |
368 | } | |
369 | if (fdt_setprop(blob, nodeoffset, "bl-version", | |
370 | PLAIN_VERSION, strlen(PLAIN_VERSION)) != 0) { | |
371 | puts("set bootloader version 'bl-version' prop. not in dtb!\n"); | |
372 | return -1; | |
373 | } | |
99f72472 HP |
374 | /* |
375 | * if no simplefb is requested through environment, we don't set up | |
376 | * one, instead we turn off backlight. | |
377 | */ | |
378 | if (getenv_ulong("simplefb", 10, 0) == 0) { | |
379 | lcdbacklight(0); | |
380 | return 0; | |
381 | } | |
382 | /* Setup simplefb devicetree node, also adapt memory-node, | |
383 | * upper limit for kernel e.g. linux is memtop-framebuffer alligned | |
384 | * to a full megabyte. | |
385 | */ | |
386 | u64 start = gd->bd->bi_dram[0].start; | |
387 | u64 size = (gd->fb_base - start) & ~0xFFFFF; | |
388 | int rc = fdt_fixup_memory_banks(blob, &start, &size, 1); | |
389 | ||
390 | if (rc) { | |
391 | puts("cannot setup simplefb: Error reserving memory!\n"); | |
392 | return rc; | |
393 | } | |
394 | rc = lcd_dt_simplefb_enable_existing_node(blob); | |
395 | if (rc) { | |
396 | puts("cannot setup simplefb: error enabling simplefb node!\n"); | |
397 | return rc; | |
398 | } | |
399 | ||
fbd5aeda HP |
400 | return 0; |
401 | } | |
402 | #else | |
403 | ||
404 | static void br_summaryscreen_printenv(char *prefix, | |
405 | char *name, char *altname, | |
406 | char *suffix) | |
407 | { | |
00caae6d | 408 | char *envval = env_get(name); |
fbd5aeda HP |
409 | if (0 != envval) { |
410 | lcd_printf("%s %s %s", prefix, envval, suffix); | |
411 | } else if (0 != altname) { | |
00caae6d | 412 | envval = env_get(altname); |
fbd5aeda HP |
413 | if (0 != envval) |
414 | lcd_printf("%s %s %s", prefix, envval, suffix); | |
415 | } else { | |
416 | lcd_printf("\n"); | |
417 | } | |
418 | } | |
419 | #endif | |
420 | void br_summaryscreen(void) | |
421 | { | |
422 | #ifdef CONFIG_USE_FDT | |
423 | br_summaryscreen_printdtb(" - B&R -", "order-no", "-\n"); | |
424 | br_summaryscreen_printdtb(" Serial/Rev :", "serial-no", " /"); | |
425 | br_summaryscreen_printdtb(" ", "hw-revision", "\n"); | |
426 | br_summaryscreen_printdtb(" MAC (IF1) :", "brmac1", "\n"); | |
427 | br_summaryscreen_printdtb(" MAC (IF2) :", "brmac2", "\n"); | |
428 | lcd_puts(" Bootloader : " PLAIN_VERSION "\n"); | |
429 | lcd_puts("\n"); | |
430 | #else | |
431 | br_summaryscreen_printenv(" - B&R -", "br_orderno", 0, "-\n"); | |
432 | br_summaryscreen_printenv(" Serial/Rev :", "br_serial", 0, "\n"); | |
433 | br_summaryscreen_printenv(" MAC (IF1) :", "br_mac1", "ethaddr", "\n"); | |
434 | br_summaryscreen_printenv(" MAC (IF2) :", "br_mac2", 0, "\n"); | |
435 | lcd_puts(" Bootloader : " PLAIN_VERSION "\n"); | |
436 | lcd_puts("\n"); | |
437 | #endif | |
438 | } | |
439 | ||
440 | void lcdpower(int on) | |
441 | { | |
442 | u32 pin, swval, i; | |
443 | #ifdef CONFIG_USE_FDT | |
47c14227 HP |
444 | if (gd->fdt_blob == NULL) { |
445 | printf("%s: don't have a valid gd->fdt_blob!\n", __func__); | |
fbd5aeda HP |
446 | return; |
447 | } | |
47c14227 | 448 | pin = FDTPROP(PATHINF, "pwrpin"); |
fbd5aeda HP |
449 | #else |
450 | pin = getenv_ulong("ds1_pwr", 16, ~0UL); | |
451 | #endif | |
452 | if (pin == ~0UL) { | |
453 | puts("no pwrpin in dtb/env, cannot powerup display!\n"); | |
454 | return; | |
455 | } | |
456 | ||
457 | for (i = 0; i < 3; i++) { | |
458 | if (pin != 0) { | |
459 | swval = pin & 0x80 ? 0 : 1; | |
460 | if (on) | |
461 | gpio_direction_output(pin & 0x7F, swval); | |
462 | else | |
463 | gpio_direction_output(pin & 0x7F, !swval); | |
464 | ||
465 | debug("switched pin %d to %d\n", pin & 0x7F, swval); | |
466 | } | |
467 | pin >>= 8; | |
468 | } | |
469 | } | |
470 | ||
471 | vidinfo_t panel_info = { | |
472 | .vl_col = 1366, /* | |
473 | * give full resolution for allocating enough | |
474 | * memory | |
475 | */ | |
476 | .vl_row = 768, | |
477 | .vl_bpix = 5, | |
478 | .priv = 0 | |
479 | }; | |
480 | ||
481 | void lcd_ctrl_init(void *lcdbase) | |
482 | { | |
483 | struct am335x_lcdpanel lcd_panel; | |
484 | #ifdef CONFIG_USE_FDT | |
485 | /* TODO: is there a better place to load the dtb ? */ | |
486 | load_devicetree(); | |
487 | #endif | |
488 | memset(&lcd_panel, 0, sizeof(struct am335x_lcdpanel)); | |
489 | if (load_lcdtiming(&lcd_panel) != 0) | |
490 | return; | |
491 | ||
492 | lcd_panel.panel_power_ctrl = &lcdpower; | |
493 | ||
494 | if (0 != am335xfb_init(&lcd_panel)) | |
495 | printf("ERROR: failed to initialize video!"); | |
496 | /* | |
497 | * modifiy panel info to 'real' resolution, to operate correct with | |
498 | * lcd-framework. | |
499 | */ | |
500 | panel_info.vl_col = lcd_panel.hactive; | |
501 | panel_info.vl_row = lcd_panel.vactive; | |
502 | ||
503 | lcd_set_flush_dcache(1); | |
504 | } | |
505 | ||
506 | void lcd_enable(void) | |
507 | { | |
fbd5aeda | 508 | br_summaryscreen(); |
99f72472 | 509 | lcdbacklight(1); |
fbd5aeda HP |
510 | } |
511 | #elif CONFIG_SPL_BUILD | |
512 | #else | |
513 | #error "LCD-support with a suitable FB-Driver is mandatory !" | |
514 | #endif /* CONFIG_LCD */ | |
515 | ||
893c04e1 HP |
516 | #ifdef CONFIG_SPL_BUILD |
517 | void pmicsetup(u32 mpupll) | |
518 | { | |
519 | int mpu_vdd; | |
520 | int usb_cur_lim; | |
521 | ||
893c04e1 HP |
522 | if (i2c_probe(TPS65217_CHIP_PM)) { |
523 | puts("PMIC (0x24) not found! skip further initalization.\n"); | |
524 | return; | |
525 | } | |
526 | ||
527 | /* Get the frequency which is defined by device fuses */ | |
528 | dpll_mpu_opp100.m = am335x_get_efuse_mpu_max_freq(cdev); | |
529 | printf("detected max. frequency: %d - ", dpll_mpu_opp100.m); | |
530 | ||
531 | if (0 != mpupll) { | |
532 | dpll_mpu_opp100.m = MPUPLL_M_1000; | |
533 | printf("retuning MPU-PLL to: %d MHz.\n", dpll_mpu_opp100.m); | |
534 | } else { | |
535 | puts("ok.\n"); | |
536 | } | |
537 | /* | |
538 | * Increase USB current limit to 1300mA or 1800mA and set | |
539 | * the MPU voltage controller as needed. | |
540 | */ | |
541 | if (dpll_mpu_opp100.m == MPUPLL_M_1000) { | |
542 | usb_cur_lim = TPS65217_USB_INPUT_CUR_LIMIT_1800MA; | |
543 | mpu_vdd = TPS65217_DCDC_VOLT_SEL_1325MV; | |
544 | } else { | |
545 | usb_cur_lim = TPS65217_USB_INPUT_CUR_LIMIT_1300MA; | |
546 | mpu_vdd = TPS65217_DCDC_VOLT_SEL_1275MV; | |
547 | } | |
548 | ||
549 | if (tps65217_reg_write(TPS65217_PROT_LEVEL_NONE, TPS65217_POWER_PATH, | |
550 | usb_cur_lim, TPS65217_USB_INPUT_CUR_LIMIT_MASK)) | |
551 | puts("tps65217_reg_write failure\n"); | |
552 | ||
553 | /* Set DCDC3 (CORE) voltage to 1.125V */ | |
554 | if (tps65217_voltage_update(TPS65217_DEFDCDC3, | |
555 | TPS65217_DCDC_VOLT_SEL_1125MV)) { | |
556 | puts("tps65217_voltage_update failure\n"); | |
557 | return; | |
558 | } | |
559 | ||
560 | /* Set CORE Frequencies to OPP100 */ | |
561 | do_setup_dpll(&dpll_core_regs, &dpll_core_opp100); | |
562 | ||
563 | /* Set DCDC2 (MPU) voltage */ | |
564 | if (tps65217_voltage_update(TPS65217_DEFDCDC2, mpu_vdd)) { | |
565 | puts("tps65217_voltage_update failure\n"); | |
566 | return; | |
567 | } | |
568 | ||
569 | /* Set LDO3 to 1.8V */ | |
570 | if (tps65217_reg_write(TPS65217_PROT_LEVEL_2, | |
571 | TPS65217_DEFLS1, | |
572 | TPS65217_LDO_VOLTAGE_OUT_1_8, | |
573 | TPS65217_LDO_MASK)) | |
574 | puts("tps65217_reg_write failure\n"); | |
575 | /* Set LDO4 to 3.3V */ | |
576 | if (tps65217_reg_write(TPS65217_PROT_LEVEL_2, | |
577 | TPS65217_DEFLS2, | |
578 | TPS65217_LDO_VOLTAGE_OUT_3_3, | |
579 | TPS65217_LDO_MASK)) | |
580 | puts("tps65217_reg_write failure\n"); | |
581 | ||
582 | /* Set MPU Frequency to what we detected now that voltages are set */ | |
583 | do_setup_dpll(&dpll_mpu_regs, &dpll_mpu_opp100); | |
fbd5aeda HP |
584 | /* Set PWR_EN bit in Status Register */ |
585 | tps65217_reg_write(TPS65217_PROT_LEVEL_NONE, | |
586 | TPS65217_STATUS, TPS65217_PWR_OFF, TPS65217_PWR_OFF); | |
893c04e1 HP |
587 | } |
588 | ||
589 | void set_uart_mux_conf(void) | |
590 | { | |
591 | enable_uart0_pin_mux(); | |
592 | } | |
593 | ||
594 | void set_mux_conf_regs(void) | |
595 | { | |
596 | enable_board_pin_mux(); | |
597 | } | |
598 | ||
599 | #endif /* CONFIG_SPL_BUILD */ | |
600 | ||
601 | #if (defined(CONFIG_DRIVER_TI_CPSW) && !defined(CONFIG_SPL_BUILD)) || \ | |
602 | (defined(CONFIG_SPL_ETH_SUPPORT) && defined(CONFIG_SPL_BUILD)) | |
603 | static void cpsw_control(int enabled) | |
604 | { | |
605 | /* VTP can be added here */ | |
606 | return; | |
607 | } | |
608 | ||
609 | /* describing port offsets of TI's CPSW block */ | |
610 | static struct cpsw_slave_data cpsw_slaves[] = { | |
611 | { | |
612 | .slave_reg_ofs = 0x208, | |
613 | .sliver_reg_ofs = 0xd80, | |
4b75fd51 | 614 | .phy_addr = 1, |
893c04e1 HP |
615 | }, |
616 | { | |
617 | .slave_reg_ofs = 0x308, | |
618 | .sliver_reg_ofs = 0xdc0, | |
4b75fd51 | 619 | .phy_addr = 2, |
893c04e1 HP |
620 | }, |
621 | }; | |
622 | ||
623 | static struct cpsw_platform_data cpsw_data = { | |
624 | .mdio_base = CPSW_MDIO_BASE, | |
625 | .cpsw_base = CPSW_BASE, | |
626 | .mdio_div = 0xff, | |
627 | .channels = 8, | |
628 | .cpdma_reg_ofs = 0x800, | |
629 | .slaves = 1, | |
630 | .slave_data = cpsw_slaves, | |
631 | .ale_reg_ofs = 0xd00, | |
632 | .ale_entries = 1024, | |
633 | .host_port_reg_ofs = 0x108, | |
634 | .hw_stats_reg_ofs = 0x900, | |
635 | .bd_ram_ofs = 0x2000, | |
636 | .mac_control = (1 << 5), | |
637 | .control = cpsw_control, | |
638 | .host_port_num = 0, | |
639 | .version = CPSW_CTRL_VERSION_2, | |
640 | }; | |
641 | #endif /* CONFIG_DRIVER_TI_CPSW, ... */ | |
642 | ||
568cfb4d | 643 | #if defined(CONFIG_DRIVER_TI_CPSW) && !defined(CONFIG_SPL_BUILD) |
893c04e1 HP |
644 | int board_eth_init(bd_t *bis) |
645 | { | |
646 | int rv = 0; | |
d301425f HP |
647 | char mac_addr[6]; |
648 | const char *mac = 0; | |
893c04e1 | 649 | uint32_t mac_hi, mac_lo; |
893c04e1 HP |
650 | /* try reading mac address from efuse */ |
651 | mac_lo = readl(&cdev->macid0l); | |
652 | mac_hi = readl(&cdev->macid0h); | |
653 | mac_addr[0] = mac_hi & 0xFF; | |
654 | mac_addr[1] = (mac_hi & 0xFF00) >> 8; | |
655 | mac_addr[2] = (mac_hi & 0xFF0000) >> 16; | |
656 | mac_addr[3] = (mac_hi & 0xFF000000) >> 24; | |
657 | mac_addr[4] = mac_lo & 0xFF; | |
658 | mac_addr[5] = (mac_lo & 0xFF00) >> 8; | |
659 | ||
00caae6d | 660 | if (!env_get("ethaddr")) { |
d301425f HP |
661 | #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_USE_FDT) |
662 | printf("<ethaddr> not set. trying DTB ... "); | |
663 | mac = dtbmacaddr(0); | |
664 | #endif | |
665 | if (!mac) { | |
666 | printf("<ethaddr> not set. validating E-fuse MAC ... "); | |
0adb5b76 | 667 | if (is_valid_ethaddr((const u8 *)mac_addr)) |
d301425f HP |
668 | mac = (const char *)mac_addr; |
669 | } | |
670 | ||
671 | if (mac) { | |
672 | printf("using: %pM on ", mac); | |
fd1e959e | 673 | eth_env_set_enetaddr("ethaddr", (const u8 *)mac); |
893c04e1 HP |
674 | } |
675 | } | |
676 | writel(MII_MODE_ENABLE, &cdev->miisel); | |
677 | cpsw_slaves[0].phy_if = PHY_INTERFACE_MODE_MII; | |
678 | cpsw_slaves[1].phy_if = PHY_INTERFACE_MODE_MII; | |
679 | ||
680 | rv = cpsw_register(&cpsw_data); | |
681 | if (rv < 0) { | |
682 | printf("Error %d registering CPSW switch\n", rv); | |
683 | return 0; | |
684 | } | |
893c04e1 HP |
685 | return rv; |
686 | } | |
568cfb4d | 687 | #endif /* defined(CONFIG_DRIVER_TI_CPSW) && !defined(CONFIG_SPL_BUILD) */ |
4aa2ba3a | 688 | #if defined(CONFIG_MMC) |
46c8ebc8 HP |
689 | int board_mmc_init(bd_t *bis) |
690 | { | |
f6877372 HS |
691 | int rc = 0; |
692 | ||
693 | rc |= omap_mmc_init(0, 0, 0, -1, -1); | |
694 | rc |= omap_mmc_init(1, 0, 0, -1, -1); | |
695 | ||
696 | return rc; | |
46c8ebc8 HP |
697 | } |
698 | #endif | |
e52e9cc7 HP |
699 | int overwrite_console(void) |
700 | { | |
701 | return 1; | |
702 | } |