]>
Commit | Line | Data |
---|---|---|
f8bbb4da KM |
1 | /* |
2 | * Copyright 2009-2011 eXMeritus, A Boeing Company | |
3 | * Copyright 2007-2009 Freescale Semiconductor, Inc. | |
4 | * | |
3765b3e7 | 5 | * SPDX-License-Identifier: GPL-2.0+ |
f8bbb4da KM |
6 | */ |
7 | ||
8 | #include <common.h> | |
9 | #include <command.h> | |
10 | #include <pci.h> | |
11 | #include <asm/processor.h> | |
12 | #include <asm/mmu.h> | |
13 | #include <asm/cache.h> | |
14 | #include <asm/immap_85xx.h> | |
15 | #include <asm/fsl_pci.h> | |
16 | #include <asm/fsl_ddr_sdram.h> | |
17 | #include <asm/io.h> | |
18 | #include <miiphy.h> | |
19 | #include <libfdt.h> | |
20 | #include <linux/ctype.h> | |
21 | #include <fdt_support.h> | |
22 | #include <fsl_mdio.h> | |
23 | #include <tsec.h> | |
24 | #include <asm/fsl_law.h> | |
25 | #include <netdev.h> | |
26 | #include <malloc.h> | |
27 | #include <i2c.h> | |
28 | #include <pca953x.h> | |
29 | ||
30 | #include "gpios.h" | |
31 | ||
32 | DECLARE_GLOBAL_DATA_PTR; | |
33 | ||
34 | int checkboard(void) | |
35 | { | |
36 | unsigned int gpio_high = 0; | |
37 | unsigned int gpio_low = 0; | |
38 | unsigned int gpio_in = 0; | |
39 | unsigned int i; | |
40 | ||
41 | puts("Board: HWW-1U-1A "); | |
42 | ||
43 | /* | |
44 | * First just figure out which CPU we're on, then use that to | |
45 | * configure the lists of other GPIOs to be programmed. | |
46 | */ | |
47 | mpc85xx_gpio_set_in(GPIO_CPU_ID); | |
48 | if (hww1u1a_is_cpu_a()) { | |
49 | puts("CPU A\n"); | |
50 | ||
51 | /* We want to turn on some LEDs */ | |
52 | gpio_high |= GPIO_CPUA_CPU_READY; | |
53 | gpio_low |= GPIO_CPUA_DEBUG_LED1; | |
54 | gpio_low |= GPIO_CPUA_DEBUG_LED2; | |
55 | ||
56 | /* Disable the unused transmitters */ | |
57 | gpio_low |= GPIO_CPUA_TDIS1A; | |
58 | gpio_high |= GPIO_CPUA_TDIS1B; | |
59 | gpio_low |= GPIO_CPUA_TDIS2A; | |
60 | gpio_high |= GPIO_CPUA_TDIS2B; | |
61 | } else { | |
62 | puts("CPU B\n"); | |
63 | ||
64 | /* We want to turn on some LEDs */ | |
65 | gpio_high |= GPIO_CPUB_CPU_READY; | |
66 | gpio_low |= GPIO_CPUB_DEBUG_LED1; | |
67 | gpio_low |= GPIO_CPUB_DEBUG_LED2; | |
68 | ||
69 | /* Enable the appropriate receivers */ | |
70 | gpio_high |= GPIO_CPUB_RMUX_SEL0A; | |
71 | gpio_high |= GPIO_CPUB_RMUX_SEL0B; | |
72 | gpio_low |= GPIO_CPUB_RMUX_SEL1A; | |
73 | gpio_low |= GPIO_CPUB_RMUX_SEL1B; | |
74 | } | |
75 | ||
76 | /* These GPIOs are common */ | |
77 | gpio_in |= IRQ_I2CINT | IRQ_FANINT | IRQ_DIMM_EVENT; | |
78 | gpio_low |= GPIO_RS422_RE; | |
79 | gpio_high |= GPIO_RS422_DE; | |
80 | ||
81 | /* Ok, now go ahead and program all of those in one go */ | |
82 | mpc85xx_gpio_set(gpio_high|gpio_low|gpio_in, | |
83 | gpio_high|gpio_low, | |
84 | gpio_high); | |
85 | ||
86 | /* | |
87 | * If things have been taken out of reset early (for example, by one | |
88 | * of the BDI3000 debuggers), then we need to put them back in reset | |
89 | * and delay a while before we continue. | |
90 | */ | |
91 | if (mpc85xx_gpio_get(GPIO_RESETS)) { | |
e76cd5d4 | 92 | ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_MPC8xxx_DDR_ADDR; |
f8bbb4da KM |
93 | |
94 | puts("Debugger detected... extra device reset enabled!\n"); | |
95 | ||
96 | /* Put stuff into reset and disable the DDR controller */ | |
97 | mpc85xx_gpio_set_low(GPIO_RESETS); | |
98 | out_be32(&ddr->sdram_cfg, 0x00000000); | |
99 | ||
100 | puts(" Waiting 1 sec for reset..."); | |
101 | for (i = 0; i < 10; i++) { | |
102 | udelay(100000); | |
103 | puts("."); | |
104 | } | |
105 | puts("\n"); | |
106 | } | |
107 | ||
108 | /* Now bring everything back out of reset again */ | |
109 | mpc85xx_gpio_set_high(GPIO_RESETS); | |
110 | return 0; | |
111 | } | |
112 | ||
113 | /* | |
114 | * This little shell function just returns whether or not it's CPU A. | |
115 | * It can be used to select the right device-tree when booting, etc. | |
116 | */ | |
117 | int do_hww1u1a_test_cpu_a(cmd_tbl_t *cmdtp, int flag, | |
118 | int argc, char * const argv[]) | |
119 | { | |
120 | if (argc > 1) | |
121 | cmd_usage(cmdtp); | |
122 | ||
123 | if (hww1u1a_is_cpu_a()) | |
124 | return 0; | |
125 | else | |
126 | return 1; | |
127 | } | |
128 | U_BOOT_CMD( | |
129 | test_cpu_a, 1, 0, do_hww1u1a_test_cpu_a, | |
130 | "Test if this is CPU A (versus B) on the eXMeritus HWW-1U-1A board", | |
131 | "" | |
132 | ); | |
133 | ||
134 | /* Create a prompt-like string: "uboot@HOSTNAME% " */ | |
135 | #define PROMPT_PREFIX "uboot@exm" | |
136 | #define PROMPT_SUFFIX "% " | |
137 | ||
138 | /* This function returns a PS1 prompt based on the serial number */ | |
139 | static char *hww1u1a_prompt; | |
140 | const char *hww1u1a_get_ps1(void) | |
141 | { | |
142 | unsigned long len, i, j; | |
143 | const char *serialnr; | |
144 | ||
145 | /* If our prompt was already set, just use that */ | |
146 | if (hww1u1a_prompt) | |
147 | return hww1u1a_prompt; | |
148 | ||
149 | /* Use our serial number if present, otherwise a default */ | |
150 | serialnr = getenv("serial#"); | |
151 | if (!serialnr || !serialnr[0]) | |
152 | serialnr = "999999-X"; | |
153 | ||
154 | /* | |
155 | * We will turn the serial number into a hostname by: | |
156 | * (A) Delete all non-alphanumerics. | |
157 | * (B) Lowercase all letters. | |
158 | * (C) Prefix "exm". | |
159 | * (D) Suffix "a" for CPU A and "b" for CPU B. | |
160 | */ | |
161 | for (i = 0, len = 0; serialnr[i]; i++) { | |
162 | if (isalnum(serialnr[i])) | |
163 | len++; | |
164 | } | |
165 | ||
166 | len += sizeof(PROMPT_PREFIX PROMPT_SUFFIX) + 1; /* Includes NUL */ | |
167 | hww1u1a_prompt = malloc(len); | |
168 | if (!hww1u1a_prompt) | |
169 | return PROMPT_PREFIX "UNKNOWN(ENOMEM)" PROMPT_SUFFIX; | |
170 | ||
171 | /* Now actually fill it in */ | |
172 | i = 0; | |
173 | ||
174 | /* Handle the prefix */ | |
175 | for (j = 0; j < sizeof(PROMPT_PREFIX) - 1; j++) | |
176 | hww1u1a_prompt[i++] = PROMPT_PREFIX[j]; | |
177 | ||
178 | /* Now the serial# part of the hostname */ | |
179 | for (j = 0; serialnr[j]; j++) | |
180 | if (isalnum(serialnr[j])) | |
181 | hww1u1a_prompt[i++] = tolower(serialnr[j]); | |
182 | ||
183 | /* Now the CPU id ("a" or "b") */ | |
184 | hww1u1a_prompt[i++] = hww1u1a_is_cpu_a() ? 'a' : 'b'; | |
185 | ||
186 | /* Finally the suffix */ | |
187 | for (j = 0; j < sizeof(PROMPT_SUFFIX); j++) | |
188 | hww1u1a_prompt[i++] = PROMPT_SUFFIX[j]; | |
189 | ||
190 | /* This should all have added up, but just in case */ | |
191 | hww1u1a_prompt[len - 1] = '\0'; | |
192 | ||
193 | /* Now we're done */ | |
194 | return hww1u1a_prompt; | |
195 | } | |
196 | ||
197 | void pci_init_board(void) | |
198 | { | |
199 | fsl_pcie_init_board(0); | |
200 | } | |
201 | ||
202 | int board_early_init_r(void) | |
203 | { | |
204 | const unsigned int flashbase = CONFIG_SYS_FLASH_BASE; | |
205 | const u8 flash_esel = find_tlb_idx((void *)flashbase, 1); | |
206 | ||
207 | /* | |
208 | * Remap bootflash region to caching-inhibited | |
209 | * so that flash can be erased properly. | |
210 | */ | |
211 | ||
212 | /* Flush d-cache and invalidate i-cache of any FLASH data */ | |
213 | flush_dcache(); | |
214 | invalidate_icache(); | |
215 | ||
216 | /* invalidate existing TLB entry for FLASH */ | |
217 | disable_tlb(flash_esel); | |
218 | ||
219 | set_tlb(1, flashbase, CONFIG_SYS_FLASH_BASE_PHYS, | |
220 | MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G, | |
221 | 0, flash_esel, BOOKE_PAGESZ_256M, 1); | |
222 | ||
223 | return 0; | |
224 | } | |
225 | ||
226 | int board_eth_init(bd_t *bis) | |
227 | { | |
228 | struct tsec_info_struct tsec_info[4]; | |
229 | struct fsl_pq_mdio_info mdio_info; | |
230 | ||
231 | SET_STD_TSEC_INFO(tsec_info[0], 1); | |
232 | SET_STD_TSEC_INFO(tsec_info[1], 2); | |
233 | SET_STD_TSEC_INFO(tsec_info[2], 3); | |
234 | ||
235 | if (hww1u1a_is_cpu_a()) | |
236 | tsec_info[2].phyaddr = TSEC3_PHY_ADDR_CPUA; | |
237 | else | |
238 | tsec_info[2].phyaddr = TSEC3_PHY_ADDR_CPUB; | |
239 | ||
240 | mdio_info.regs = (struct tsec_mii_mng *)CONFIG_SYS_MDIO_BASE_ADDR; | |
241 | mdio_info.name = DEFAULT_MII_NAME; | |
242 | fsl_pq_mdio_init(bis, &mdio_info); | |
243 | ||
244 | tsec_eth_init(bis, tsec_info, 3); | |
245 | return pci_eth_init(bis); | |
246 | } | |
247 | ||
248 | void ft_board_setup(void *blob, bd_t *bd) | |
249 | { | |
250 | phys_addr_t base; | |
251 | phys_size_t size; | |
252 | ||
253 | ft_cpu_setup(blob, bd); | |
254 | ||
255 | base = getenv_bootm_low(); | |
256 | size = getenv_bootm_size(); | |
257 | ||
258 | fdt_fixup_memory(blob, (u64)base, (u64)size); | |
259 | ||
260 | FT_FSL_PCI_SETUP; | |
261 | } |