blob: 91c80353edd61a36ec2c24443afa59cdccafc7c7 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
York Sun03017032015-03-20 19:28:23 -07002/*
3 * Copyright 2015 Freescale Semiconductor
York Sun03017032015-03-20 19:28:23 -07004 */
5#include <common.h>
Simon Glass0af6e2d2019-08-01 09:46:52 -06006#include <env.h>
York Sun03017032015-03-20 19:28:23 -07007#include <malloc.h>
8#include <errno.h>
9#include <netdev.h>
10#include <fsl_ifc.h>
11#include <fsl_ddr.h>
12#include <asm/io.h>
13#include <fdt_support.h>
Masahiro Yamada75f82d02018-03-05 01:20:11 +090014#include <linux/libfdt.h>
York Sun03017032015-03-20 19:28:23 -070015#include <fsl-mc/fsl_mc.h>
Simon Glass9d1f6192019-08-02 09:44:25 -060016#include <env_internal.h>
York Sun03017032015-03-20 19:28:23 -070017#include <i2c.h>
Priyanka Jain2657e432015-06-29 15:39:40 +053018#include <rtc.h>
Mingkai Hu0e58b512015-10-26 19:47:50 +080019#include <asm/arch/soc.h>
Haikun Wanga6cd9da2015-06-26 19:58:12 +080020#include <hwconfig.h>
Saksham Jainc0c38d22016-03-23 16:24:35 +053021#include <fsl_sec.h>
Santan Kumarc61c6992017-03-07 11:21:03 +053022#include <asm/arch/ppa.h>
23
York Sun03017032015-03-20 19:28:23 -070024
25#include "../common/qixis.h"
Prabhakar Kushwaha122bcfd2015-11-09 16:42:07 +053026#include "ls2080aqds_qixis.h"
Priyanka Jain53e7ec02017-01-19 11:12:28 +053027#include "../common/vid.h"
York Sun03017032015-03-20 19:28:23 -070028
Haikun Wanga6cd9da2015-06-26 19:58:12 +080029#define PIN_MUX_SEL_SDHC 0x00
30#define PIN_MUX_SEL_DSPI 0x0a
Yuan Yao2ec85842016-06-08 18:24:52 +080031#define SCFG_QSPICLKCTRL_DIV_20 (5 << 27)
Haikun Wanga6cd9da2015-06-26 19:58:12 +080032
33#define SET_SDHC_MUX_SEL(reg, value) ((reg & 0xf0) | value)
34
York Sun03017032015-03-20 19:28:23 -070035DECLARE_GLOBAL_DATA_PTR;
36
Haikun Wanga6cd9da2015-06-26 19:58:12 +080037enum {
38 MUX_TYPE_SDHC,
39 MUX_TYPE_DSPI,
40};
41
York Sun03017032015-03-20 19:28:23 -070042unsigned long long get_qixis_addr(void)
43{
44 unsigned long long addr;
45
46 if (gd->flags & GD_FLG_RELOC)
47 addr = QIXIS_BASE_PHYS;
48 else
49 addr = QIXIS_BASE_PHYS_EARLY;
50
51 /*
52 * IFC address under 256MB is mapped to 0x30000000, any address above
53 * is mapped to 0x5_10000000 up to 4GB.
54 */
55 addr = addr > 0x10000000 ? addr + 0x500000000ULL : addr + 0x30000000;
56
57 return addr;
58}
59
60int checkboard(void)
61{
62 char buf[64];
63 u8 sw;
64 static const char *const freq[] = {"100", "125", "156.25",
65 "100 separate SSCG"};
66 int clock;
67
Prabhakar Kushwaha67f2e9c2015-05-28 14:54:07 +053068 cpu_name(buf);
69 printf("Board: %s-QDS, ", buf);
70
York Sun03017032015-03-20 19:28:23 -070071 sw = QIXIS_READ(arch);
York Sun03017032015-03-20 19:28:23 -070072 printf("Board Arch: V%d, ", sw >> 4);
73 printf("Board version: %c, boot from ", (sw & 0xf) + 'A' - 1);
74
Prabhakar Kushwaha67f2e9c2015-05-28 14:54:07 +053075 memset((u8 *)buf, 0x00, ARRAY_SIZE(buf));
76
York Sun03017032015-03-20 19:28:23 -070077 sw = QIXIS_READ(brdcfg[0]);
78 sw = (sw & QIXIS_LBMAP_MASK) >> QIXIS_LBMAP_SHIFT;
79
80 if (sw < 0x8)
81 printf("vBank: %d\n", sw);
82 else if (sw == 0x8)
83 puts("PromJet\n");
84 else if (sw == 0x9)
85 puts("NAND\n");
Yuan Yao331c87c2016-06-08 18:25:00 +080086 else if (sw == 0xf)
87 puts("QSPI\n");
York Sun03017032015-03-20 19:28:23 -070088 else if (sw == 0x15)
89 printf("IFCCard\n");
90 else
91 printf("invalid setting of SW%u\n", QIXIS_LBMAP_SWITCH);
92
93 printf("FPGA: v%d (%s), build %d",
94 (int)QIXIS_READ(scver), qixis_read_tag(buf),
95 (int)qixis_read_minor());
96 /* the timestamp string contains "\n" at the end */
97 printf(" on %s", qixis_read_time(buf));
98
99 /*
100 * Display the actual SERDES reference clocks as configured by the
101 * dip switches on the board. Note that the SWx registers could
102 * technically be set to force the reference clocks to match the
103 * values that the SERDES expects (or vice versa). For now, however,
104 * we just display both values and hope the user notices when they
105 * don't match.
106 */
107 puts("SERDES1 Reference : ");
108 sw = QIXIS_READ(brdcfg[2]);
109 clock = (sw >> 6) & 3;
110 printf("Clock1 = %sMHz ", freq[clock]);
111 clock = (sw >> 4) & 3;
112 printf("Clock2 = %sMHz", freq[clock]);
113
114 puts("\nSERDES2 Reference : ");
115 clock = (sw >> 2) & 3;
116 printf("Clock1 = %sMHz ", freq[clock]);
117 clock = (sw >> 0) & 3;
118 printf("Clock2 = %sMHz\n", freq[clock]);
119
120 return 0;
121}
122
123unsigned long get_board_sys_clk(void)
124{
125 u8 sysclk_conf = QIXIS_READ(brdcfg[1]);
126
127 switch (sysclk_conf & 0x0F) {
128 case QIXIS_SYSCLK_83:
129 return 83333333;
130 case QIXIS_SYSCLK_100:
131 return 100000000;
132 case QIXIS_SYSCLK_125:
133 return 125000000;
134 case QIXIS_SYSCLK_133:
135 return 133333333;
136 case QIXIS_SYSCLK_150:
137 return 150000000;
138 case QIXIS_SYSCLK_160:
139 return 160000000;
140 case QIXIS_SYSCLK_166:
141 return 166666666;
142 }
143 return 66666666;
144}
145
146unsigned long get_board_ddr_clk(void)
147{
148 u8 ddrclk_conf = QIXIS_READ(brdcfg[1]);
149
150 switch ((ddrclk_conf & 0x30) >> 4) {
151 case QIXIS_DDRCLK_100:
152 return 100000000;
153 case QIXIS_DDRCLK_125:
154 return 125000000;
155 case QIXIS_DDRCLK_133:
156 return 133333333;
157 }
158 return 66666666;
159}
160
161int select_i2c_ch_pca9547(u8 ch)
162{
163 int ret;
Chuanhua Han1ab68c72019-07-26 19:24:01 +0800164#ifdef CONFIG_DM_I2C
165 struct udevice *dev;
York Sun03017032015-03-20 19:28:23 -0700166
Chuanhua Han1ab68c72019-07-26 19:24:01 +0800167 ret = i2c_get_chip_for_busnum(0, I2C_MUX_PCA_ADDR_PRI, 1, &dev);
168 if (!ret)
169 ret = dm_i2c_write(dev, 0, &ch, 1);
170
171#else
York Sun03017032015-03-20 19:28:23 -0700172 ret = i2c_write(I2C_MUX_PCA_ADDR_PRI, 0, 1, &ch, 1);
Chuanhua Han1ab68c72019-07-26 19:24:01 +0800173#endif
York Sun03017032015-03-20 19:28:23 -0700174 if (ret) {
175 puts("PCA: failed to select proper channel\n");
176 return ret;
177 }
178
179 return 0;
180}
181
Haikun Wanga6cd9da2015-06-26 19:58:12 +0800182int config_board_mux(int ctrl_type)
183{
184 u8 reg5;
185
186 reg5 = QIXIS_READ(brdcfg[5]);
187
188 switch (ctrl_type) {
189 case MUX_TYPE_SDHC:
190 reg5 = SET_SDHC_MUX_SEL(reg5, PIN_MUX_SEL_SDHC);
191 break;
192 case MUX_TYPE_DSPI:
193 reg5 = SET_SDHC_MUX_SEL(reg5, PIN_MUX_SEL_DSPI);
194 break;
195 default:
196 printf("Wrong mux interface type\n");
197 return -1;
198 }
199
200 QIXIS_WRITE(brdcfg[5], reg5);
201
202 return 0;
203}
204
York Sun03017032015-03-20 19:28:23 -0700205int board_init(void)
206{
Haikun Wanga6cd9da2015-06-26 19:58:12 +0800207 char *env_hwconfig;
208 u32 __iomem *dcfg_ccsr = (u32 __iomem *)DCFG_BASE;
209 u32 val;
210
York Sun03017032015-03-20 19:28:23 -0700211 init_final_memctl_regs();
212
Haikun Wanga6cd9da2015-06-26 19:58:12 +0800213 val = in_le32(dcfg_ccsr + DCFG_RCWSR13 / 4);
214
Simon Glass64b723f2017-08-03 12:22:12 -0600215 env_hwconfig = env_get("hwconfig");
Haikun Wanga6cd9da2015-06-26 19:58:12 +0800216
217 if (hwconfig_f("dspi", env_hwconfig) &&
218 DCFG_RCWSR13_DSPI == (val & (u32)(0xf << 8)))
219 config_board_mux(MUX_TYPE_DSPI);
220 else
221 config_board_mux(MUX_TYPE_SDHC);
222
Yuan Yao86f42d72016-06-08 18:24:57 +0800223#if defined(CONFIG_NAND) && defined(CONFIG_FSL_QSPI)
224 val = in_le32(dcfg_ccsr + DCFG_RCWSR15 / 4);
225
226 if (DCFG_RCWSR15_IFCGRPABASE_QSPI == (val & (u32)0x3))
227 QIXIS_WRITE(brdcfg[9],
228 (QIXIS_READ(brdcfg[9]) & 0xf8) |
229 FSL_QIXIS_BRDCFG9_QSPI);
230#endif
231
York Sun03017032015-03-20 19:28:23 -0700232#ifdef CONFIG_ENV_IS_NOWHERE
233 gd->env_addr = (ulong)&default_environment[0];
234#endif
235 select_i2c_ch_pca9547(I2C_MUX_CH_DEFAULT);
Chuanhua Han1ab68c72019-07-26 19:24:01 +0800236
Chuanhua Han4f97aac2019-07-26 19:24:00 +0800237#ifdef CONFIG_RTC_ENABLE_32KHZ_OUTPUT
Chuanhua Han1ab68c72019-07-26 19:24:01 +0800238#ifdef CONFIG_DM_I2C
239 rtc_enable_32khz_output(0, CONFIG_SYS_I2C_RTC_ADDR);
240#else
Priyanka Jain2657e432015-06-29 15:39:40 +0530241 rtc_enable_32khz_output();
Chuanhua Han4f97aac2019-07-26 19:24:00 +0800242#endif
Chuanhua Han1ab68c72019-07-26 19:24:01 +0800243#endif
244
Udit Agarwalc83ea8a2017-08-16 07:13:29 -0400245#ifdef CONFIG_FSL_CAAM
246 sec_init();
247#endif
Santan Kumarc61c6992017-03-07 11:21:03 +0530248
249#ifdef CONFIG_FSL_LS_PPA
250 ppa_init();
251#endif
252
York Sun03017032015-03-20 19:28:23 -0700253 return 0;
254}
255
256int board_early_init_f(void)
257{
Yuan Yao5a89cce2016-06-08 18:24:54 +0800258#ifdef CONFIG_SYS_I2C_EARLY_INIT
259 i2c_early_init_f();
260#endif
York Sun03017032015-03-20 19:28:23 -0700261 fsl_lsch3_early_init_f();
Yuan Yao2ec85842016-06-08 18:24:52 +0800262#ifdef CONFIG_FSL_QSPI
263 /* input clk: 1/2 platform clk, output: input/20 */
264 out_le32(SCFG_BASE + SCFG_QSPICLKCTLR, SCFG_QSPICLKCTRL_DIV_20);
265#endif
York Sun03017032015-03-20 19:28:23 -0700266 return 0;
267}
268
Priyanka Jain53e7ec02017-01-19 11:12:28 +0530269int misc_init_r(void)
270{
271 if (adjust_vdd(0))
272 printf("Warning: Adjusting core voltage failed.\n");
273
274 return 0;
275}
276
York Sun03017032015-03-20 19:28:23 -0700277void detail_board_ddr_info(void)
278{
279 puts("\nDDR ");
280 print_size(gd->bd->bi_dram[0].size + gd->bd->bi_dram[1].size, "");
281 print_ddr_info(0);
Prabhakar Kushwaha122bcfd2015-11-09 16:42:07 +0530282#ifdef CONFIG_SYS_FSL_HAS_DP_DDR
York Suncbe8e1c2016-04-04 11:41:26 -0700283 if (soc_has_dp_ddr() && gd->bd->bi_dram[2].size) {
York Sun03017032015-03-20 19:28:23 -0700284 puts("\nDP-DDR ");
285 print_size(gd->bd->bi_dram[2].size, "");
286 print_ddr_info(CONFIG_DP_DDR_CTRL);
287 }
Prabhakar Kushwaha122bcfd2015-11-09 16:42:07 +0530288#endif
York Sun03017032015-03-20 19:28:23 -0700289}
290
York Sun03017032015-03-20 19:28:23 -0700291#if defined(CONFIG_ARCH_MISC_INIT)
292int arch_misc_init(void)
293{
York Sun03017032015-03-20 19:28:23 -0700294 return 0;
295}
296#endif
297
Santan Kumar1afa9002017-05-05 15:42:29 +0530298#if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD)
York Sun03017032015-03-20 19:28:23 -0700299void fdt_fixup_board_enet(void *fdt)
300{
301 int offset;
302
Stuart Yodera3466152016-03-02 16:37:13 -0600303 offset = fdt_path_offset(fdt, "/soc/fsl-mc");
York Sun03017032015-03-20 19:28:23 -0700304
305 if (offset < 0)
Stuart Yodera3466152016-03-02 16:37:13 -0600306 offset = fdt_path_offset(fdt, "/fsl-mc");
York Sun03017032015-03-20 19:28:23 -0700307
308 if (offset < 0) {
309 printf("%s: ERROR: fsl-mc node not found in device tree (error %d)\n",
310 __func__, offset);
311 return;
312 }
313
Mian Yousaf Kaukab97124652018-12-18 14:01:17 +0100314 if (get_mc_boot_status() == 0 &&
315 (is_lazy_dpl_addr_valid() || get_dpl_apply_status() == 0))
York Sun03017032015-03-20 19:28:23 -0700316 fdt_status_okay(fdt, offset);
317 else
318 fdt_status_fail(fdt, offset);
319}
Alexander Graf2ebeb442016-11-17 01:02:57 +0100320
321void board_quiesce_devices(void)
322{
323 fsl_mc_ldpaa_exit(gd->bd);
324}
York Sun03017032015-03-20 19:28:23 -0700325#endif
326
327#ifdef CONFIG_OF_BOARD_SETUP
328int ft_board_setup(void *blob, bd_t *bd)
329{
Bhupesh Sharma0b10a1a2015-05-28 14:54:10 +0530330 u64 base[CONFIG_NR_DRAM_BANKS];
331 u64 size[CONFIG_NR_DRAM_BANKS];
York Sun03017032015-03-20 19:28:23 -0700332
333 ft_cpu_setup(blob, bd);
334
Bhupesh Sharma0b10a1a2015-05-28 14:54:10 +0530335 /* fixup DT for the two GPP DDR banks */
336 base[0] = gd->bd->bi_dram[0].start;
337 size[0] = gd->bd->bi_dram[0].size;
338 base[1] = gd->bd->bi_dram[1].start;
339 size[1] = gd->bd->bi_dram[1].size;
340
York Sun4de24ef2017-03-06 09:02:28 -0800341#ifdef CONFIG_RESV_RAM
342 /* reduce size if reserved memory is within this bank */
343 if (gd->arch.resv_ram >= base[0] &&
344 gd->arch.resv_ram < base[0] + size[0])
345 size[0] = gd->arch.resv_ram - base[0];
346 else if (gd->arch.resv_ram >= base[1] &&
347 gd->arch.resv_ram < base[1] + size[1])
348 size[1] = gd->arch.resv_ram - base[1];
349#endif
350
Bhupesh Sharma0b10a1a2015-05-28 14:54:10 +0530351 fdt_fixup_memory_banks(blob, base, size, 2);
York Sun03017032015-03-20 19:28:23 -0700352
Nipun Guptad6912642018-08-20 16:01:14 +0530353 fdt_fsl_mc_fixup_iommu_map_entry(blob);
354
Sriram Dash9fd465c2016-09-16 17:12:15 +0530355 fsl_fdt_fixup_dr_usb(blob, bd);
Sriram Dash01820952016-06-13 09:58:36 +0530356
Santan Kumar1afa9002017-05-05 15:42:29 +0530357#if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD)
York Sun03017032015-03-20 19:28:23 -0700358 fdt_fixup_board_enet(blob);
York Sun03017032015-03-20 19:28:23 -0700359#endif
360
361 return 0;
362}
363#endif
364
365void qixis_dump_switch(void)
366{
367 int i, nr_of_cfgsw;
368
369 QIXIS_WRITE(cms[0], 0x00);
370 nr_of_cfgsw = QIXIS_READ(cms[1]);
371
372 puts("DIP switch settings dump:\n");
373 for (i = 1; i <= nr_of_cfgsw; i++) {
374 QIXIS_WRITE(cms[0], i);
375 printf("SW%d = (0x%02x)\n", i, QIXIS_READ(cms[1]));
376 }
377}