1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2024 PHYTEC Messtechnik GmbH
4  * Author: Daniel Schultz <d.schultz@phytec.de>
5  */
6 
7 #include <asm/arch/hardware.h>
8 
9 #include "am6_som_detection.h"
10 
11 extern struct phytec_eeprom_data eeprom_data;
12 
13 #if IS_ENABLED(CONFIG_PHYTEC_AM62_SOM_DETECTION) || \
14 	IS_ENABLED(CONFIG_PHYTEC_AM62A_SOM_DETECTION) || \
15 	IS_ENABLED(CONFIG_PHYTEC_AM64_SOM_DETECTION)
16 
17 /* Check if the SoM is actually one of the following products:
18  * - phyCORE-AM62x
19  * - phyCORE-AM62Ax
20  * - phyCORE-AM64x
21  *
22  * Returns 0 in case it's a known SoM. Otherwise, returns -1.
23  */
phytec_am6_detect(struct phytec_eeprom_data * data)24 int phytec_am6_detect(struct phytec_eeprom_data *data)
25 {
26 	char *opt;
27 	u8 som;
28 
29 	if (!data)
30 		data = &eeprom_data;
31 
32 	/* We cannot do the check for early API revisions */
33 	if (!data->valid || data->payload.api_rev < PHYTEC_API_REV2)
34 		return -1;
35 
36 	som = data->payload.data.data_api2.som_no;
37 	debug("%s: som id: %u\n", __func__, som);
38 
39 	opt = phytec_get_opt(data);
40 	if (!opt)
41 		return -1;
42 
43 	if (som == PHYTEC_AM62X_SOM && soc_is_am62x())
44 		return 0;
45 
46 	if (som == PHYTEC_AM62AX_SOM && soc_is_am62ax())
47 		return 0;
48 
49 	if (som == PHYTEC_AM64X_SOM && soc_is_am64x())
50 		return 0;
51 
52 	return -1;
53 }
54 
phytec_check_opt(struct phytec_eeprom_data * data,u8 option)55 static u8 phytec_check_opt(struct phytec_eeprom_data *data, u8 option)
56 {
57 	char *opt;
58 
59 	if (!data)
60 		data = &eeprom_data;
61 
62 	if (!data->valid || data->payload.api_rev < PHYTEC_API_REV2)
63 		return PHYTEC_EEPROM_INVAL;
64 
65 	if (option > 8)
66 		return PHYTEC_EEPROM_INVAL;
67 
68 	opt = phytec_get_opt(data);
69 	if (opt)
70 		return PHYTEC_GET_OPTION(opt[option]);
71 	return PHYTEC_EEPROM_INVAL;
72 }
73 
74 /*
75  * Reads LPDDR4 ram size from EEPROM.
76  *
77  * returns:
78  *  - The size
79  *  - PHYTEC_EEPROM_INVAL when the data is invalid.
80  */
phytec_get_am6_ddr_size(struct phytec_eeprom_data * data)81 u8 __maybe_unused phytec_get_am6_ddr_size(struct phytec_eeprom_data *data)
82 {
83 	u8 ddr_id = phytec_check_opt(data, 3);
84 
85 	pr_debug("%s: ddr id: %u\n", __func__, ddr_id);
86 	return ddr_id;
87 }
88 
89 /*
90  * Reads SPI-NOR flash size and type from EEPROM.
91  *
92  * returns:
93  *  - PHYTEC_EEPROM_VALUE_X if no SPI is poulated.
94  *  - Otherwise a board depended code for the size.
95  *  - PHYTEC_EEPROM_INVAL when the data is invalid.
96  */
phytec_get_am6_spi(struct phytec_eeprom_data * data)97 u8 __maybe_unused phytec_get_am6_spi(struct phytec_eeprom_data *data)
98 {
99 	u8 spi = phytec_check_opt(data, 5);
100 
101 	pr_debug("%s: spi: %u\n", __func__, spi);
102 	return spi;
103 }
104 
105 /*
106  * Reads Ethernet phy information from EEPROM.
107  *
108  * returns:
109  *  - 0x0 no ethernet phy is populated.
110  *  - 0x1 if 10/100/1000 MBit Phy is populated.
111  *  - PHYTEC_EEPROM_INVAL when the data is invalid.
112  */
phytec_get_am6_eth(struct phytec_eeprom_data * data)113 u8 __maybe_unused phytec_get_am6_eth(struct phytec_eeprom_data *data)
114 {
115 	u8 eth = phytec_check_opt(data, 6);
116 
117 	pr_debug("%s: eth: %u\n", __func__, eth);
118 	return eth;
119 }
120 
121 /*
122  * Reads RTC information from EEPROM.
123  *
124  * returns:
125  *  - 0 if no RTC is poulated.
126  *  - 1 if it is populated.
127  *  - PHYTEC_EEPROM_INVAL when the data is invalid.
128  */
phytec_get_am6_rtc(struct phytec_eeprom_data * data)129 u8 __maybe_unused phytec_get_am6_rtc(struct phytec_eeprom_data *data)
130 {
131 	u8 rtc = phytec_check_opt(data, 7);
132 
133 	pr_debug("%s: rtc: %u\n", __func__, rtc);
134 	return rtc;
135 }
136 
137 #else
138 
phytec_am6_detect(struct phytec_eeprom_data * data)139 inline int __maybe_unused phytec_am6_detect(struct phytec_eeprom_data *data)
140 {
141 	return -1;
142 }
143 
144 inline u8 __maybe_unused
phytec_get_am6_ddr_size(struct phytec_eeprom_data * data)145 phytec_get_am6_ddr_size(struct phytec_eeprom_data *data)
146 {
147 	return PHYTEC_EEPROM_INVAL;
148 }
149 
phytec_get_am6_spi(struct phytec_eeprom_data * data)150 inline u8 __maybe_unused phytec_get_am6_spi(struct phytec_eeprom_data *data)
151 {
152 	return PHYTEC_EEPROM_INVAL;
153 }
154 
phytec_get_am6_eth(struct phytec_eeprom_data * data)155 inline u8 __maybe_unused phytec_get_am6_eth(struct phytec_eeprom_data *data)
156 {
157 	return PHYTEC_EEPROM_INVAL;
158 }
159 
phytec_get_am6_rtc(struct phytec_eeprom_data * data)160 inline u8 __maybe_unused phytec_get_am6_rtc(struct phytec_eeprom_data *data)
161 {
162 	return PHYTEC_EEPROM_INVAL;
163 }
164 #endif
165