1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3 * soc-intel-quirks.h - prototypes for quirk autodetection
4 *
5 * Copyright (c) 2019, Intel Corporation.
6 *
7 */
8
9 #ifndef _SND_SOC_INTEL_QUIRKS_H
10 #define _SND_SOC_INTEL_QUIRKS_H
11
12 #if IS_ENABLED(CONFIG_X86)
13
14 #include <linux/dmi.h>
15 #include <asm/cpu_device_id.h>
16 #include <asm/intel-family.h>
17 #include <asm/iosf_mbi.h>
18
19 #define SOC_INTEL_IS_CPU(soc, type) \
20 static inline bool soc_intel_is_##soc(void) \
21 { \
22 static const struct x86_cpu_id soc##_cpu_ids[] = { \
23 X86_MATCH_INTEL_FAM6_MODEL(type, NULL), \
24 {} \
25 }; \
26 const struct x86_cpu_id *id; \
27 \
28 id = x86_match_cpu(soc##_cpu_ids); \
29 if (id) \
30 return true; \
31 return false; \
32 }
33
34 SOC_INTEL_IS_CPU(byt, ATOM_SILVERMONT);
35 SOC_INTEL_IS_CPU(cht, ATOM_AIRMONT);
36 SOC_INTEL_IS_CPU(apl, ATOM_GOLDMONT);
37 SOC_INTEL_IS_CPU(glk, ATOM_GOLDMONT_PLUS);
38 SOC_INTEL_IS_CPU(cml, KABYLAKE_L);
39
soc_intel_is_byt_cr(struct platform_device * pdev)40 static inline bool soc_intel_is_byt_cr(struct platform_device *pdev)
41 {
42 /*
43 * List of systems which:
44 * 1. Use a non CR version of the Bay Trail SoC
45 * 2. Contain at least 6 interrupt resources so that the
46 * platform_get_resource(pdev, IORESOURCE_IRQ, 5) check below
47 * succeeds
48 * 3. Despite 1. and 2. still have their IPC IRQ at index 0 rather then 5
49 *
50 * This needs to be here so that it can be shared between the SST and
51 * SOF drivers. We rely on the compiler to optimize this out in files
52 * where soc_intel_is_byt_cr is not used.
53 */
54 static const struct dmi_system_id force_bytcr_table[] = {
55 { /* Lenovo Yoga Tablet 2 series */
56 .matches = {
57 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
58 DMI_MATCH(DMI_PRODUCT_FAMILY, "YOGATablet2"),
59 },
60 },
61 {}
62 };
63 struct device *dev = &pdev->dev;
64 int status = 0;
65
66 if (!soc_intel_is_byt())
67 return false;
68
69 if (dmi_check_system(force_bytcr_table))
70 return true;
71
72 if (iosf_mbi_available()) {
73 u32 bios_status;
74
75 status = iosf_mbi_read(BT_MBI_UNIT_PMC, /* 0x04 PUNIT */
76 MBI_REG_READ, /* 0x10 */
77 0x006, /* BIOS_CONFIG */
78 &bios_status);
79
80 if (status) {
81 dev_err(dev, "could not read PUNIT BIOS_CONFIG\n");
82 } else {
83 /* bits 26:27 mirror PMIC options */
84 bios_status = (bios_status >> 26) & 3;
85
86 if (bios_status == 1 || bios_status == 3) {
87 dev_info(dev, "Detected Baytrail-CR platform\n");
88 return true;
89 }
90
91 dev_info(dev, "BYT-CR not detected\n");
92 }
93 } else {
94 dev_info(dev, "IOSF_MBI not available, no BYT-CR detection\n");
95 }
96
97 if (!platform_get_resource(pdev, IORESOURCE_IRQ, 5)) {
98 /*
99 * Some devices detected as BYT-T have only a single IRQ listed,
100 * causing platform_get_irq with index 5 to return -ENXIO.
101 * The correct IRQ in this case is at index 0, as on BYT-CR.
102 */
103 dev_info(dev, "Falling back to Baytrail-CR platform\n");
104 return true;
105 }
106
107 return false;
108 }
109
110 #else
111
soc_intel_is_byt_cr(struct platform_device * pdev)112 static inline bool soc_intel_is_byt_cr(struct platform_device *pdev)
113 {
114 return false;
115 }
116
soc_intel_is_byt(void)117 static inline bool soc_intel_is_byt(void)
118 {
119 return false;
120 }
121
soc_intel_is_cht(void)122 static inline bool soc_intel_is_cht(void)
123 {
124 return false;
125 }
126
soc_intel_is_apl(void)127 static inline bool soc_intel_is_apl(void)
128 {
129 return false;
130 }
131
soc_intel_is_glk(void)132 static inline bool soc_intel_is_glk(void)
133 {
134 return false;
135 }
136
soc_intel_is_cml(void)137 static inline bool soc_intel_is_cml(void)
138 {
139 return false;
140 }
141 #endif
142
143 #endif /* _SND_SOC_INTEL_QUIRKS_H */
144