blob: c6c96ed19cb32012c748f7a0c60348ee93d352cd [file] [log] [blame]
Teresa Remmetc6dd9c62023-08-17 10:57:07 +02001// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (C) 2023 PHYTEC Messtechnik GmbH
4 * Author: Teresa Remmet <t.remmet@phytec.de>
5 */
6
7#include <common.h>
8#include <asm/arch/sys_proto.h>
9#include <dm/device.h>
10#include <dm/uclass.h>
11#include <i2c.h>
12#include <u-boot/crc.h>
13
14#include "imx8m_som_detection.h"
15
16extern struct phytec_eeprom_data eeprom_data;
17
18/* Check if the SoM is actually one of the following products:
19 * - i.MX8MM
20 * - i.MX8MN
21 * - i.MX8MP
22 * - i.MX8MQ
23 *
24 * Returns 0 in case it's a known SoM. Otherwise, returns -1.
25 */
26u8 __maybe_unused phytec_imx8m_detect(struct phytec_eeprom_data *data)
27{
28 char *opt;
29 u8 som;
30
31 /* We can not do the check for early API revisions */
32 if (data->api_rev < PHYTEC_API_REV2)
33 return -1;
34
35 if (!data)
36 data = &eeprom_data;
37
38 som = data->data.data_api2.som_no;
39 debug("%s: som id: %u\n", __func__, som);
40
41 opt = phytec_get_opt(data);
42 if (!opt)
43 return -1;
44
45 if (som == PHYTEC_IMX8MP_SOM && is_imx8mp())
46 return 0;
47
48 if (som == PHYTEC_IMX8MM_SOM) {
49 if ((PHYTEC_GET_OPTION(opt[0]) != 0) &&
50 (PHYTEC_GET_OPTION(opt[1]) == 0) && is_imx8mm())
51 return 0;
52 else if ((PHYTEC_GET_OPTION(opt[0]) == 0) &&
53 (PHYTEC_GET_OPTION(opt[1]) != 0) && is_imx8mn())
54 return 0;
55 }
56
57 if (som == PHYTEC_IMX8MQ_SOM && is_imx8mq())
58 return 0;
59
60 pr_err("%s: SoM ID does not match. Wrong EEPROM data?\n", __func__);
61 return -1;
62}
63
64/*
65 * All PHYTEC i.MX8M boards have RAM size definition at the
66 * same location.
67 */
68u8 __maybe_unused phytec_get_imx8m_ddr_size(struct phytec_eeprom_data *data)
69{
70 char *opt;
71 u8 ddr_id;
72
73 if (!data)
74 data = &eeprom_data;
75
76 opt = phytec_get_opt(data);
77 if (opt)
78 ddr_id = PHYTEC_GET_OPTION(opt[2]);
79 else
80 ddr_id = PHYTEC_EEPROM_INVAL;
81
82 debug("%s: ddr id: %u\n", __func__, ddr_id);
83 return ddr_id;
84}
85
86/*
87 * Filter SPI-NOR flash information. All i.MX8M boards have this at
88 * the same location.
89 * returns: 0x0 if no SPI is populated. Otherwise a board depended
90 * code for the size. PHYTEC_EEPROM_INVAL when the data is invalid.
91 */
92u8 __maybe_unused phytec_get_imx8m_spi(struct phytec_eeprom_data *data)
93{
94 char *opt;
95 u8 spi;
96
97 if (!data)
98 data = &eeprom_data;
99
100 if (data->api_rev < PHYTEC_API_REV2)
101 return PHYTEC_EEPROM_INVAL;
102
103 opt = phytec_get_opt(data);
104 if (opt)
105 spi = PHYTEC_GET_OPTION(opt[4]);
106 else
107 spi = PHYTEC_EEPROM_INVAL;
108
109 debug("%s: spi: %u\n", __func__, spi);
110 return spi;
111}
112
113/*
114 * Filter ethernet phy information. All i.MX8M boards have this at
115 * the same location.
116 * returns: 0x0 if no ethernet phy is populated. 0x1 if it is populated.
117 * PHYTEC_EEPROM_INVAL when the data is invalid.
118 */
119u8 __maybe_unused phytec_get_imx8m_eth(struct phytec_eeprom_data *data)
120{
121 char *opt;
122 u8 eth;
123
124 if (!data)
125 data = &eeprom_data;
126
127 if (data->api_rev < PHYTEC_API_REV2)
128 return PHYTEC_EEPROM_INVAL;
129
130 opt = phytec_get_opt(data);
131 if (opt) {
132 eth = PHYTEC_GET_OPTION(opt[5]);
133 eth &= 0x1;
134 } else {
135 eth = PHYTEC_EEPROM_INVAL;
136 }
137
138 debug("%s: eth: %u\n", __func__, eth);
139 return eth;
140}
141
142/*
143 * Filter RTC information for phyCORE-i.MX8MP.
144 * returns: 0 if no RTC is populated. 1 if it is populated.
145 * PHYTEC_EEPROM_INVAL when the data is invalid.
146 */
147u8 __maybe_unused phytec_get_imx8mp_rtc(struct phytec_eeprom_data *data)
148{
149 char *opt;
150 u8 rtc;
151
152 if (!data)
153 data = &eeprom_data;
154
155 if (data->api_rev < PHYTEC_API_REV2)
156 return PHYTEC_EEPROM_INVAL;
157
158 opt = phytec_get_opt(data);
159 if (opt) {
160 rtc = PHYTEC_GET_OPTION(opt[5]);
161 rtc &= 0x4;
162 rtc = !(rtc >> 2);
163 } else {
164 rtc = PHYTEC_EEPROM_INVAL;
165 }
166 debug("%s: rtc: %u\n", __func__, rtc);
167 return rtc;
168}