]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/freescale/mpc837xemds/mpc837xemds.c
83xx: Add eSDHC support on 8379 EMDS board
[karo-tx-uboot.git] / board / freescale / mpc837xemds / mpc837xemds.c
1 /*
2  * Copyright (C) 2007 Freescale Semiconductor, Inc.
3  * Dave Liu <daveliu@freescale.com>
4  *
5  * CREDITS: Kim Phillips contribute to LIBFDT code
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 of
10  * the License, or (at your option) any later version.
11  */
12
13 #include <common.h>
14 #include <i2c.h>
15 #include <asm/io.h>
16 #include <asm/fsl_serdes.h>
17 #include <spd_sdram.h>
18 #include <tsec.h>
19 #include <libfdt.h>
20 #include <fdt_support.h>
21 #include "pci.h"
22 #include "../common/pq-mds-pib.h"
23
24 int board_early_init_f(void)
25 {
26         struct immap __iomem *im = (struct immap __iomem *)CONFIG_SYS_IMMR;
27         u8 *bcsr = (u8 *)CONFIG_SYS_BCSR;
28
29         /* Enable flash write */
30         bcsr[0x9] &= ~0x04;
31         /* Clear all of the interrupt of BCSR */
32         bcsr[0xe] = 0xff;
33
34 #ifdef CONFIG_MMC
35         /* Set SPI_SD, SER_SD, and IRQ4_WP so that SD signals go through */
36         bcsr[0xc] |= 0x4c;
37
38         /* Set proper bits in SICR to allow SD signals through */
39         clrsetbits_be32(&im->sysconf.sicrl, SICRL_USB_B, SICRL_USB_B_SD);
40
41         clrsetbits_be32(&im->sysconf.sicrh, (SICRH_GPIO2_E | SICRH_SPI),
42                         (SICRH_GPIO2_E_SD | SICRH_SPI_SD));
43
44 #endif
45
46 #ifdef CONFIG_FSL_SERDES
47         immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
48         u32 spridr = in_be32(&immr->sysconf.spridr);
49
50         /* we check only part num, and don't look for CPU revisions */
51         switch (PARTID_NO_E(spridr)) {
52         case SPR_8377:
53                 fsl_setup_serdes(CONFIG_FSL_SERDES1, FSL_SERDES_PROTO_SATA,
54                                 FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V);
55                 break;
56         case SPR_8378:
57                 fsl_setup_serdes(CONFIG_FSL_SERDES1, FSL_SERDES_PROTO_SGMII,
58                                 FSL_SERDES_CLK_125, FSL_SERDES_VDD_1V);
59                 break;
60         case SPR_8379:
61                 fsl_setup_serdes(CONFIG_FSL_SERDES1, FSL_SERDES_PROTO_SATA,
62                                 FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V);
63                 fsl_setup_serdes(CONFIG_FSL_SERDES2, FSL_SERDES_PROTO_SATA,
64                                 FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V);
65                 break;
66         default:
67                 printf("serdes not configured: unknown CPU part number: "
68                                 "%04x\n", spridr >> 16);
69                 break;
70         }
71 #endif /* CONFIG_FSL_SERDES */
72         return 0;
73 }
74
75 #if defined(CONFIG_TSEC1) || defined(CONFIG_TSEC2)
76 int board_eth_init(bd_t *bd)
77 {
78         struct tsec_info_struct tsec_info[2];
79         struct immap __iomem *im = (struct immap __iomem *)CONFIG_SYS_IMMR;
80         u32 rcwh = in_be32(&im->reset.rcwh);
81         u32 tsec_mode;
82         int num = 0;
83
84         /* New line after Net: */
85         printf("\n");
86
87 #ifdef CONFIG_TSEC1
88         SET_STD_TSEC_INFO(tsec_info[num], 1);
89
90         printf(CONFIG_TSEC1_NAME ": ");
91
92         tsec_mode = rcwh & HRCWH_TSEC1M_MASK;
93         if (tsec_mode == HRCWH_TSEC1M_IN_RGMII) {
94                 printf("RGMII\n");
95                 /* this is default, no need to fixup */
96         } else if (tsec_mode == HRCWH_TSEC1M_IN_SGMII) {
97                 printf("SGMII\n");
98                 tsec_info[num].phyaddr = TSEC1_PHY_ADDR_SGMII;
99                 tsec_info[num].flags = TSEC_GIGABIT;
100         } else {
101                 printf("unsupported PHY type\n");
102         }
103         num++;
104 #endif
105 #ifdef CONFIG_TSEC2
106         SET_STD_TSEC_INFO(tsec_info[num], 2);
107
108         printf(CONFIG_TSEC2_NAME ": ");
109
110         tsec_mode = rcwh & HRCWH_TSEC2M_MASK;
111         if (tsec_mode == HRCWH_TSEC2M_IN_RGMII) {
112                 printf("RGMII\n");
113                 /* this is default, no need to fixup */
114         } else if (tsec_mode == HRCWH_TSEC2M_IN_SGMII) {
115                 printf("SGMII\n");
116                 tsec_info[num].phyaddr = TSEC2_PHY_ADDR_SGMII;
117                 tsec_info[num].flags = TSEC_GIGABIT;
118         } else {
119                 printf("unsupported PHY type\n");
120         }
121         num++;
122 #endif
123         return tsec_eth_init(bd, tsec_info, num);
124 }
125
126 static void __ft_tsec_fixup(void *blob, bd_t *bd, const char *alias,
127                             int phy_addr)
128 {
129         const char *phy_type = "sgmii";
130         const u32 *ph;
131         int off;
132         int err;
133
134         off = fdt_path_offset(blob, alias);
135         if (off < 0) {
136                 printf("WARNING: could not find %s alias: %s.\n", alias,
137                         fdt_strerror(off));
138                 return;
139         }
140
141         err = fdt_setprop(blob, off, "phy-connection-type", phy_type,
142                           strlen(phy_type) + 1);
143         if (err) {
144                 printf("WARNING: could not set phy-connection-type for %s: "
145                         "%s.\n", alias, fdt_strerror(err));
146                 return;
147         }
148
149         ph = (u32 *)fdt_getprop(blob, off, "phy-handle", 0);
150         if (!ph) {
151                 printf("WARNING: could not get phy-handle for %s.\n",
152                         alias);
153                 return;
154         }
155
156         off = fdt_node_offset_by_phandle(blob, *ph);
157         if (off < 0) {
158                 printf("WARNING: could not get phy node for %s: %s\n", alias,
159                         fdt_strerror(off));
160                 return;
161         }
162
163         phy_addr = cpu_to_fdt32(phy_addr);
164         err = fdt_setprop(blob, off, "reg", &phy_addr, sizeof(phy_addr));
165         if (err < 0) {
166                 printf("WARNING: could not set phy node's reg for %s: "
167                         "%s.\n", alias, fdt_strerror(err));
168                 return;
169         }
170 }
171
172 static void ft_tsec_fixup(void *blob, bd_t *bd)
173 {
174         struct immap __iomem *im = (struct immap __iomem *)CONFIG_SYS_IMMR;
175         u32 rcwh = in_be32(&im->reset.rcwh);
176         u32 tsec_mode;
177
178 #ifdef CONFIG_TSEC1
179         tsec_mode = rcwh & HRCWH_TSEC1M_MASK;
180         if (tsec_mode == HRCWH_TSEC1M_IN_SGMII)
181                 __ft_tsec_fixup(blob, bd, "ethernet0", TSEC1_PHY_ADDR_SGMII);
182 #endif
183
184 #ifdef CONFIG_TSEC2
185         tsec_mode = rcwh & HRCWH_TSEC2M_MASK;
186         if (tsec_mode == HRCWH_TSEC2M_IN_SGMII)
187                 __ft_tsec_fixup(blob, bd, "ethernet1", TSEC2_PHY_ADDR_SGMII);
188 #endif
189 }
190 #else
191 static inline void ft_tsec_fixup(void *blob, bd_t *bd) {}
192 #endif /* defined(CONFIG_TSEC1) || defined(CONFIG_TSEC2) */
193
194 int board_early_init_r(void)
195 {
196 #ifdef CONFIG_PQ_MDS_PIB
197         pib_init();
198 #endif
199         return 0;
200 }
201
202 #if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRC)
203 extern void ddr_enable_ecc(unsigned int dram_size);
204 #endif
205 int fixed_sdram(void);
206
207 phys_size_t initdram(int board_type)
208 {
209         volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
210         u32 msize = 0;
211
212         if ((im->sysconf.immrbar & IMMRBAR_BASE_ADDR) != (u32) im)
213                 return -1;
214
215 #if defined(CONFIG_SPD_EEPROM)
216         msize = spd_sdram();
217 #else
218         msize = fixed_sdram();
219 #endif
220
221 #if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRC)
222         /* Initialize DDR ECC byte */
223         ddr_enable_ecc(msize * 1024 * 1024);
224 #endif
225
226         /* return total bus DDR size(bytes) */
227         return (msize * 1024 * 1024);
228 }
229
230 #if !defined(CONFIG_SPD_EEPROM)
231 /*************************************************************************
232  *  fixed sdram init -- doesn't use serial presence detect.
233  ************************************************************************/
234 int fixed_sdram(void)
235 {
236         volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
237         u32 msize = CONFIG_SYS_DDR_SIZE * 1024 * 1024;
238         u32 msize_log2 = __ilog2(msize);
239
240         im->sysconf.ddrlaw[0].bar = CONFIG_SYS_DDR_SDRAM_BASE & 0xfffff000;
241         im->sysconf.ddrlaw[0].ar = LBLAWAR_EN | (msize_log2 - 1);
242
243 #if (CONFIG_SYS_DDR_SIZE != 512)
244 #warning Currenly any ddr size other than 512 is not supported
245 #endif
246         im->sysconf.ddrcdr = CONFIG_SYS_DDRCDR_VALUE;
247         udelay(50000);
248
249         im->ddr.sdram_clk_cntl = CONFIG_SYS_DDR_SDRAM_CLK_CNTL;
250         udelay(1000);
251
252         im->ddr.csbnds[0].csbnds = CONFIG_SYS_DDR_CS0_BNDS;
253         im->ddr.cs_config[0] = CONFIG_SYS_DDR_CS0_CONFIG;
254         udelay(1000);
255
256         im->ddr.timing_cfg_0 = CONFIG_SYS_DDR_TIMING_0;
257         im->ddr.timing_cfg_1 = CONFIG_SYS_DDR_TIMING_1;
258         im->ddr.timing_cfg_2 = CONFIG_SYS_DDR_TIMING_2;
259         im->ddr.timing_cfg_3 = CONFIG_SYS_DDR_TIMING_3;
260         im->ddr.sdram_cfg = CONFIG_SYS_DDR_SDRAM_CFG;
261         im->ddr.sdram_cfg2 = CONFIG_SYS_DDR_SDRAM_CFG2;
262         im->ddr.sdram_mode = CONFIG_SYS_DDR_MODE;
263         im->ddr.sdram_mode2 = CONFIG_SYS_DDR_MODE2;
264         im->ddr.sdram_interval = CONFIG_SYS_DDR_INTERVAL;
265         __asm__ __volatile__("sync");
266         udelay(1000);
267
268         im->ddr.sdram_cfg |= SDRAM_CFG_MEM_EN;
269         udelay(2000);
270         return CONFIG_SYS_DDR_SIZE;
271 }
272 #endif /*!CONFIG_SYS_SPD_EEPROM */
273
274 int checkboard(void)
275 {
276         puts("Board: Freescale MPC837xEMDS\n");
277         return 0;
278 }
279
280 #ifdef CONFIG_PCI
281 int board_pci_host_broken(void)
282 {
283         struct immap __iomem *im = (struct immap __iomem *)CONFIG_SYS_IMMR;
284         const u32 rcw_mask = HRCWH_PCI1_ARBITER_ENABLE | HRCWH_PCI_HOST;
285         const char *pci_ea = getenv("pci_external_arbiter");
286
287         /* It's always OK in case of external arbiter. */
288         if (pci_ea && !strcmp(pci_ea, "yes"))
289                 return 0;
290
291         if ((in_be32(&im->reset.rcwh) & rcw_mask) != rcw_mask)
292                 return 1;
293
294         return 0;
295 }
296
297 static void ft_pci_fixup(void *blob, bd_t *bd)
298 {
299         const char *status = "broken (no arbiter)";
300         int off;
301         int err;
302
303         off = fdt_path_offset(blob, "pci0");
304         if (off < 0) {
305                 printf("WARNING: could not find pci0 alias: %s.\n",
306                         fdt_strerror(off));
307                 return;
308         }
309
310         err = fdt_setprop(blob, off, "status", status, strlen(status) + 1);
311         if (err) {
312                 printf("WARNING: could not set status for pci0: %s.\n",
313                         fdt_strerror(err));
314                 return;
315         }
316 }
317 #endif
318
319 #if defined(CONFIG_OF_BOARD_SETUP)
320 void ft_board_setup(void *blob, bd_t *bd)
321 {
322         ft_cpu_setup(blob, bd);
323         ft_tsec_fixup(blob, bd);
324         fdt_fixup_dr_usb(blob, bd);
325 #ifdef CONFIG_PCI
326         ft_pci_setup(blob, bd);
327         if (board_pci_host_broken())
328                 ft_pci_fixup(blob, bd);
329         ft_pcie_fixup(blob, bd);
330 #endif
331 }
332 #endif /* CONFIG_OF_BOARD_SETUP */