]>
Commit | Line | Data |
---|---|---|
8b0044ff OZ |
1 | /* |
2 | * Copyright 2013-2015 Arcturus Networks, Inc. | |
3 | * http://www.arcturusnetworks.com/products/ucp1020/ | |
4 | * by Oleksandr G Zhadan et al. | |
5 | * based on board/freescale/p1_p2_rdb_pc/spl.c | |
6 | * original copyright follows: | |
7 | * Copyright 2013 Freescale Semiconductor, Inc. | |
8 | * | |
9 | * SPDX-License-Identifier: GPL-2.0+ | |
10 | */ | |
11 | ||
12 | #include <common.h> | |
13 | #include <command.h> | |
14 | #include <hwconfig.h> | |
15 | #include <pci.h> | |
16 | #include <i2c.h> | |
17 | #include <miiphy.h> | |
18 | #include <libfdt.h> | |
19 | #include <fdt_support.h> | |
20 | #include <fsl_mdio.h> | |
21 | #include <tsec.h> | |
22 | #include <ioports.h> | |
23 | #include <netdev.h> | |
24 | #include <micrel.h> | |
25 | #include <spi_flash.h> | |
26 | #include <mmc.h> | |
27 | #include <linux/ctype.h> | |
28 | #include <asm/fsl_serdes.h> | |
29 | #include <asm/gpio.h> | |
30 | #include <asm/processor.h> | |
31 | #include <asm/mmu.h> | |
32 | #include <asm/cache.h> | |
33 | #include <asm/immap_85xx.h> | |
34 | #include <asm/fsl_pci.h> | |
35 | #include <fsl_ddr_sdram.h> | |
36 | #include <asm/io.h> | |
37 | #include <asm/fsl_law.h> | |
38 | #include <asm/fsl_lbc.h> | |
39 | #include <asm/mp.h> | |
40 | #include "ucp1020.h" | |
41 | ||
42 | void spi_set_speed(struct spi_slave *slave, uint hz) | |
43 | { | |
44 | /* TO DO: It's actially have to be in spi/ */ | |
45 | } | |
46 | ||
47 | /* | |
48 | * To be compatible with cmd_gpio | |
49 | */ | |
50 | int name_to_gpio(const char *name) | |
51 | { | |
52 | int gpio = 31 - simple_strtoul(name, NULL, 10); | |
53 | ||
54 | if (gpio < 16) | |
55 | gpio = -1; | |
56 | ||
57 | return gpio; | |
58 | } | |
59 | ||
60 | void board_gpio_init(void) | |
61 | { | |
62 | int i; | |
63 | char envname[8], *val; | |
64 | ||
65 | for (i = 0; i < GPIO_MAX_NUM; i++) { | |
66 | sprintf(envname, "GPIO%d", i); | |
00caae6d | 67 | val = env_get(envname); |
8b0044ff OZ |
68 | if (val) { |
69 | char direction = toupper(val[0]); | |
70 | char level = toupper(val[1]); | |
71 | ||
72 | if (direction == 'I') { | |
73 | gpio_direction_input(i); | |
74 | } else { | |
75 | if (direction == 'O') { | |
76 | if (level == '1') | |
77 | gpio_direction_output(i, 1); | |
78 | else | |
79 | gpio_direction_output(i, 0); | |
80 | } | |
81 | } | |
82 | } | |
83 | } | |
84 | ||
00caae6d | 85 | val = env_get("PCIE_OFF"); |
8b0044ff OZ |
86 | if (val) { |
87 | gpio_direction_input(GPIO_PCIE1_EN); | |
88 | gpio_direction_input(GPIO_PCIE2_EN); | |
89 | } else { | |
90 | gpio_direction_output(GPIO_PCIE1_EN, 1); | |
91 | gpio_direction_output(GPIO_PCIE2_EN, 1); | |
92 | } | |
93 | ||
00caae6d | 94 | val = env_get("SDHC_CDWP_OFF"); |
8b0044ff OZ |
95 | if (!val) { |
96 | ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); | |
97 | ||
98 | setbits_be32(&gur->pmuxcr, | |
99 | (MPC85xx_PMUXCR_SDHC_CD | MPC85xx_PMUXCR_SDHC_WP)); | |
100 | } | |
101 | } | |
102 | ||
103 | int board_early_init_f(void) | |
104 | { | |
105 | return 0; /* Just in case. Could be disable in config file */ | |
106 | } | |
107 | ||
108 | int checkboard(void) | |
109 | { | |
110 | printf("Board: %s\n", CONFIG_BOARDNAME_LOCAL); | |
111 | board_gpio_init(); | |
112 | printf("SD/MMC: 4-bit Mode\n"); | |
113 | ||
114 | return 0; | |
115 | } | |
116 | ||
117 | #ifdef CONFIG_PCI | |
118 | void pci_init_board(void) | |
119 | { | |
120 | fsl_pcie_init_board(0); | |
121 | } | |
122 | #endif | |
123 | ||
124 | int board_early_init_r(void) | |
125 | { | |
126 | const unsigned int flashbase = CONFIG_SYS_FLASH_BASE; | |
127 | const u8 flash_esel = find_tlb_idx((void *)flashbase, 1); | |
128 | ||
129 | /* | |
130 | * Remap Boot flash region to caching-inhibited | |
131 | * so that flash can be erased properly. | |
132 | */ | |
133 | ||
134 | /* Flush d-cache and invalidate i-cache of any FLASH data */ | |
135 | flush_dcache(); | |
136 | invalidate_icache(); | |
137 | ||
138 | /* invalidate existing TLB entry for flash */ | |
139 | disable_tlb(flash_esel); | |
140 | ||
141 | set_tlb(1, flashbase, CONFIG_SYS_FLASH_BASE_PHYS, /* tlb, epn, rpn */ | |
142 | MAS3_SX | MAS3_SW | MAS3_SR, MAS2_I | MAS2_G, /* perms, wimge */ | |
143 | 0, flash_esel, BOOKE_PAGESZ_64M, 1);/* ts, esel, tsize, iprot */ | |
144 | ||
145 | return 0; | |
146 | } | |
147 | ||
148 | int board_phy_config(struct phy_device *phydev) | |
149 | { | |
150 | #if defined(CONFIG_PHY_MICREL_KSZ9021) | |
151 | int regval; | |
152 | static int cnt; | |
153 | ||
154 | if (cnt++ == 0) | |
155 | printf("PHYs address ["); | |
156 | ||
157 | if (phydev->addr == TSEC1_PHY_ADDR || phydev->addr == TSEC3_PHY_ADDR) { | |
158 | regval = | |
159 | ksz9021_phy_extended_read(phydev, | |
160 | MII_KSZ9021_EXT_STRAP_STATUS); | |
161 | /* | |
162 | * min rx data delay | |
163 | */ | |
164 | ksz9021_phy_extended_write(phydev, | |
165 | MII_KSZ9021_EXT_RGMII_RX_DATA_SKEW, | |
166 | 0x6666); | |
167 | /* | |
168 | * max rx/tx clock delay, min rx/tx control | |
169 | */ | |
170 | ksz9021_phy_extended_write(phydev, | |
171 | MII_KSZ9021_EXT_RGMII_CLOCK_SKEW, | |
172 | 0xf6f6); | |
173 | printf("0x%x", (regval & 0x1f)); | |
174 | } else { | |
175 | printf("0x%x", (TSEC2_PHY_ADDR & 0x1f)); | |
176 | } | |
177 | if (cnt == 3) | |
178 | printf("] "); | |
179 | else | |
180 | printf(","); | |
181 | #endif | |
182 | ||
183 | #if defined(CONFIG_PHY_MICREL_KSZ9031_DEBUG) | |
184 | regval = ksz9031_phy_extended_read(phydev, 2, 0x01, 0x4000); | |
185 | if (regval >= 0) | |
186 | printf(" (ADDR 0x%x) ", regval & 0x1f); | |
187 | #endif | |
188 | ||
189 | return 0; | |
190 | } | |
191 | ||
192 | int last_stage_init(void) | |
193 | { | |
194 | static char newkernelargs[256]; | |
195 | static u8 id1[16]; | |
196 | static u8 id2; | |
197 | struct mmc *mmc; | |
198 | char *sval, *kval; | |
199 | ||
200 | if (i2c_read(CONFIG_SYS_I2C_IDT6V49205B, 7, 1, &id1[0], 2) < 0) { | |
201 | printf("Error reading i2c IDT6V49205B information!\n"); | |
202 | } else { | |
203 | printf("IDT6V49205B(0x%02x): ready\n", id1[1]); | |
204 | i2c_read(CONFIG_SYS_I2C_IDT6V49205B, 4, 1, &id1[0], 2); | |
205 | if (!(id1[1] & 0x02)) { | |
206 | id1[1] |= 0x02; | |
207 | i2c_write(CONFIG_SYS_I2C_IDT6V49205B, 4, 1, &id1[0], 2); | |
208 | asm("nop; nop"); | |
209 | } | |
210 | } | |
211 | ||
212 | if (i2c_read(CONFIG_SYS_I2C_NCT72_ADDR, 0xFE, 1, &id2, 1) < 0) | |
213 | printf("Error reading i2c NCT72 information!\n"); | |
214 | else | |
215 | printf("NCT72(0x%x): ready\n", id2); | |
216 | ||
00caae6d | 217 | kval = env_get("kernelargs"); |
8b0044ff OZ |
218 | |
219 | mmc = find_mmc_device(0); | |
220 | if (mmc) | |
221 | if (!mmc_init(mmc)) { | |
222 | printf("MMC/SD card detected\n"); | |
223 | if (kval) { | |
224 | int n = strlen(defkargs); | |
225 | char *tmp = strstr(kval, defkargs); | |
226 | ||
227 | *tmp = 0; | |
228 | strcpy(newkernelargs, kval); | |
229 | strcat(newkernelargs, " "); | |
230 | strcat(newkernelargs, mmckargs); | |
231 | strcat(newkernelargs, " "); | |
232 | strcat(newkernelargs, &tmp[n]); | |
382bee57 | 233 | env_set("kernelargs", newkernelargs); |
8b0044ff | 234 | } else { |
382bee57 | 235 | env_set("kernelargs", mmckargs); |
8b0044ff OZ |
236 | } |
237 | } | |
238 | get_arc_info(); | |
239 | ||
240 | if (kval) { | |
00caae6d | 241 | sval = env_get("SERIAL"); |
8b0044ff OZ |
242 | if (sval) { |
243 | strcpy(newkernelargs, "SN="); | |
244 | strcat(newkernelargs, sval); | |
245 | strcat(newkernelargs, " "); | |
246 | strcat(newkernelargs, kval); | |
382bee57 | 247 | env_set("kernelargs", newkernelargs); |
8b0044ff OZ |
248 | } |
249 | } else { | |
250 | printf("Error reading kernelargs env variable!\n"); | |
251 | } | |
252 | ||
253 | return 0; | |
254 | } | |
255 | ||
256 | int board_eth_init(bd_t *bis) | |
257 | { | |
258 | struct fsl_pq_mdio_info mdio_info; | |
259 | struct tsec_info_struct tsec_info[4]; | |
260 | #ifdef CONFIG_TSEC2 | |
261 | ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); | |
262 | #endif | |
263 | int num = 0; | |
264 | ||
265 | #ifdef CONFIG_TSEC1 | |
266 | SET_STD_TSEC_INFO(tsec_info[num], 1); | |
267 | num++; | |
268 | #endif | |
269 | #ifdef CONFIG_TSEC2 | |
270 | SET_STD_TSEC_INFO(tsec_info[num], 2); | |
271 | if (is_serdes_configured(SGMII_TSEC2)) { | |
272 | if (!(in_be32(&gur->pordevsr) & MPC85xx_PORDEVSR_SGMII2_DIS)) { | |
273 | puts("eTSEC2 is in sgmii mode.\n"); | |
274 | tsec_info[num].flags |= TSEC_SGMII; | |
275 | tsec_info[num].phyaddr = TSEC2_PHY_ADDR_SGMII; | |
276 | } | |
277 | } | |
278 | num++; | |
279 | #endif | |
280 | #ifdef CONFIG_TSEC3 | |
281 | SET_STD_TSEC_INFO(tsec_info[num], 3); | |
282 | num++; | |
283 | #endif | |
284 | ||
285 | if (!num) { | |
286 | printf("No TSECs initialized\n"); | |
287 | return 0; | |
288 | } | |
289 | ||
290 | mdio_info.regs = (struct tsec_mii_mng *)CONFIG_SYS_MDIO_BASE_ADDR; | |
291 | mdio_info.name = DEFAULT_MII_NAME; | |
292 | ||
293 | fsl_pq_mdio_init(bis, &mdio_info); | |
294 | ||
295 | tsec_eth_init(bis, tsec_info, num); | |
296 | ||
297 | return pci_eth_init(bis); | |
298 | } | |
299 | ||
300 | #ifdef CONFIG_OF_BOARD_SETUP | |
301 | int ft_board_setup(void *blob, bd_t *bd) | |
302 | { | |
303 | phys_addr_t base; | |
304 | phys_size_t size; | |
305 | const char *soc_usb_compat = "fsl-usb2-dr"; | |
306 | int err, usb1_off, usb2_off; | |
307 | ||
308 | ft_cpu_setup(blob, bd); | |
309 | ||
723806cc SG |
310 | base = env_get_bootm_low(); |
311 | size = env_get_bootm_size(); | |
8b0044ff OZ |
312 | |
313 | fdt_fixup_memory(blob, (u64)base, (u64)size); | |
314 | ||
315 | FT_FSL_PCI_SETUP; | |
316 | ||
317 | #if defined(CONFIG_HAS_FSL_DR_USB) | |
a5c289b9 | 318 | fsl_fdt_fixup_dr_usb(blob, bd); |
8b0044ff OZ |
319 | #endif |
320 | ||
321 | #if defined(CONFIG_SDCARD) || defined(CONFIG_SPIFLASH) | |
322 | /* Delete eLBC node as it is muxed with USB2 controller */ | |
323 | if (hwconfig("usb2")) { | |
324 | const char *soc_elbc_compat = "fsl,p1020-elbc"; | |
325 | int off = fdt_node_offset_by_compatible(blob, -1, | |
326 | soc_elbc_compat); | |
327 | if (off < 0) { | |
328 | printf | |
329 | ("WARNING: could not find compatible node %s: %s\n", | |
330 | soc_elbc_compat, fdt_strerror(off)); | |
331 | return off; | |
332 | } | |
333 | err = fdt_del_node(blob, off); | |
334 | if (err < 0) { | |
335 | printf("WARNING: could not remove %s: %s\n", | |
336 | soc_elbc_compat, fdt_strerror(err)); | |
337 | } | |
338 | return err; | |
339 | } | |
340 | #endif | |
341 | ||
342 | /* Delete USB2 node as it is muxed with eLBC */ | |
343 | usb1_off = fdt_node_offset_by_compatible(blob, -1, soc_usb_compat); | |
344 | if (usb1_off < 0) { | |
345 | printf("WARNING: could not find compatible node %s: %s.\n", | |
346 | soc_usb_compat, fdt_strerror(usb1_off)); | |
347 | return usb1_off; | |
348 | } | |
349 | usb2_off = | |
350 | fdt_node_offset_by_compatible(blob, usb1_off, soc_usb_compat); | |
351 | if (usb2_off < 0) { | |
352 | printf("WARNING: could not find compatible node %s: %s.\n", | |
353 | soc_usb_compat, fdt_strerror(usb2_off)); | |
354 | return usb2_off; | |
355 | } | |
356 | err = fdt_del_node(blob, usb2_off); | |
357 | if (err < 0) { | |
358 | printf("WARNING: could not remove %s: %s.\n", | |
359 | soc_usb_compat, fdt_strerror(err)); | |
360 | } | |
361 | return 0; | |
362 | } | |
363 | #endif |