1 // SPDX-License-Identifier: GPL-2.0+
2 
3 #include <common.h>
4 #include <asm/io.h>
5 #include <asm/spl.h>
6 #include <asm/arch-fsl-layerscape/fsl_serdes.h>
7 #include <asm/arch-fsl-layerscape/soc.h>
8 
9 #define DCFG_RCWSR25 0x160
10 #define GPINFO_HW_VARIANT_MASK 0xff
11 
12 #define SERDES_LNDGCR0		0x1ea08c0
13 #define   LNDGCR0_PROTS_MASK	GENMASK(11, 7)
14 #define   LNDGCR0_PROTS_SATA	(0x2 << 7)
15 #define SERDES_LNDGCR1		0x1ea08c4
16 #define   LNDGCR1_RDAT_INV	BIT(31)
17 
18 /*
19  * On this board the SMARC PCIe lane D might be switched to SATA mode. This
20  * makes sense if this lane is connected to a Mini PCI slot and a mSATA card
21  * is plugged in. In this case, the RX pair is swapped and we need to invert
22  * the received data.
23  */
fixup_sata_rx_polarity(void)24 static void fixup_sata_rx_polarity(void)
25 {
26 	u32 prot = in_le32(SERDES_LNDGCR0) & LNDGCR0_PROTS_MASK;
27 	u32 tmp;
28 
29 	if (prot == LNDGCR0_PROTS_SATA) {
30 		tmp = in_le32(SERDES_LNDGCR1);
31 		tmp |= LNDGCR1_RDAT_INV;
32 		out_le32(SERDES_LNDGCR1, tmp);
33 	}
34 }
35 
sl28_variant(void)36 int sl28_variant(void)
37 {
38 	return in_le32(DCFG_BASE + DCFG_RCWSR25) & GPINFO_HW_VARIANT_MASK;
39 }
40 
board_fit_config_name_match(const char * name)41 int board_fit_config_name_match(const char *name)
42 {
43 	int variant = sl28_variant();
44 
45 	switch (variant) {
46 	case 1:
47 		return strcmp(name, "fsl-ls1028a-kontron-sl28-var1");
48 	case 2:
49 		return strcmp(name, "fsl-ls1028a-kontron-sl28-var2");
50 	case 3:
51 		return strcmp(name, "fsl-ls1028a-kontron-sl28-var3");
52 	case 4:
53 		return strcmp(name, "fsl-ls1028a-kontron-sl28-var4");
54 	default:
55 		return strcmp(name, "fsl-ls1028a-kontron-sl28");
56 	}
57 }
58 
board_boot_order(u32 * spl_boot_list)59 void board_boot_order(u32 *spl_boot_list)
60 {
61 	spl_boot_list[0] = BOOT_DEVICE_SPI;
62 }
63 
board_early_init_f(void)64 int board_early_init_f(void)
65 {
66 	fixup_sata_rx_polarity();
67 	fsl_lsch3_early_init_f();
68 
69 	return 0;
70 }
71