1 /***********************license start***********************************
2 * Copyright (C) 2021-2026 Marvell.
3 * SPDX-License-Identifier: BSD-3-Clause
4 * https://spdx.org/licenses
5 ***********************license end**************************************/
6
7 /**
8 * @file
9 *
10 * Functions for determining which chip you are running on.
11 *
12 * <hr>$Revision: 49448 $<hr>
13 * @addtogroup chips
14 * @{
15 */
16
17
18 /* Flag bits in top byte. The top byte of MIDR_EL1 is defined
19 as ox43, the Cavium implementer code. In this number, bits
20 7,5,4 are defined as zero. We use these bits to signal
21 that revision numbers should be ignored. It isn't ideal
22 that these are in the middle of an already defined field,
23 but this keeps the model numbers as 32 bits */
24 #define __OM_IGNORE_REVISION 0x80000000
25 #define __OM_IGNORE_MINOR_REVISION 0x20000000
26 #define __OM_IGNORE_MODEL 0x10000000
27
28 /* Variant, or major pass numbers are stored in bits [23:20] */
29 #define __OM_PASS_SHIFT 8
30 #define __OM_PASS_MASK (0x7 << __OM_PASS_SHIFT)
31
32 /*
33 * Partnum is divied into two fields for our chips. Bits [7:4] are the
34 * processor family. Bits [3:0] are the processor ID
35 */
36 #define __OM_PARTNUM_MASK 0xff
37 #define __OM_FAMILY_MASK 0xf0
38
39 /* Minor pass numbers are stored in bits [13:11] */
40 #define __OM_MINOR_SHIFT 11
41 #define __OM_MINOR_MASK (0x7 << __OM_MINOR_SHIFT)
42
43 #define __OM_BUILD(partnum, major, minor) \
44 ((partnum) | \
45 (((major) - 1) << __OM_PASS_SHIFT) | \
46 ((minor) << __OM_MINOR_SHIFT))
47
48
49 /* Per chip definitions */
50 #define ODYSSEY_PASS1_0 __OM_BUILD(0xBF, 1, 0)
51 #define ODYSSEY_PASS1_1 __OM_BUILD(0xBF, 1, 1)
52 #define ODYSSEY (ODYSSEY_CN10KA_PASS1_0 | __OM_IGNORE_REVISION)
53 #define ODYSSEY_PASS1_X (ODYSSEY_CN10KA_PASS1_0 | __OM_IGNORE_MINOR_REVISION)
54
55 #define FUS_CACHE0_ADDRESS 0x87e003001000ll
56
57 /**
58 * Return non-zero if the chip matech the passed model.
59 *
60 * @param arg_model One of the ODYSSEY_* constants for chip models and
61 * passes
62 *
63 * @return Non-zero if match
64 */
65 static inline int ody_is_model(uint32_t arg_model) __attribute__ ((pure, always_inline));
ody_is_model(uint32_t arg_model)66 static inline int ody_is_model(uint32_t arg_model)
67 {
68 uint64_t fuse_val = *(volatile uint64_t *)FUS_CACHE0_ADDRESS;
69 uint64_t mask;
70 uint32_t my_model = fuse_val & 0xffffffff;
71
72 if (arg_model & __OM_IGNORE_REVISION)
73 mask = __OM_PARTNUM_MASK;
74 else if (arg_model & __OM_IGNORE_MINOR_REVISION)
75 mask = __OM_PARTNUM_MASK | __OM_PASS_MASK;
76 else
77 mask = __OM_PARTNUM_MASK | __OM_PASS_MASK | __OM_MINOR_MASK;
78
79 return ((arg_model) & mask) == (my_model & mask);
80 }
81
82 /**
83 * Return non-zero if the die is in an alternate package. The
84 * normal is_model() checks will treat alternate package parts
85 * as all the same, where this function can be used to detect
86 * them. The return value is the upper two bits of
87 * MIO_FUS_DAT2[chip_id]. Most alternate packages use bit 6,
88 * which will return 1 here. Parts with a second alternative
89 * will use bit 7, which will return 2.
90 *
91 * @param arg_model One of the constants for chip models and
92 * passes
93 *
94 * @return Non-zero if an alternate package
95 * 0 = Normal package
96 */
97 extern int ody_is_altpkg(uint32_t arg_model);
98
99 #define ODY_MODEL_MAX_SKU 32 /* Maximum length of SKU is 31 plus zero terminator */
100
101 /**
102 * Return the SKU string for a chip
103 *
104 * @return Chip's SKU
105 */
106 extern const char *ody_model_get_sku(void);
107
108 /** @} */
109