xref: /freebsd/sys/contrib/dev/rtw89/acpi.c (revision 6d67aabd63555ab62a2f2b7f52a75ef100a2fe75)
1e2340276SBjoern A. Zeeb // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2e2340276SBjoern A. Zeeb /* Copyright(c) 2021-2023  Realtek Corporation
3e2340276SBjoern A. Zeeb  */
4e2340276SBjoern A. Zeeb 
5e2340276SBjoern A. Zeeb #include <linux/acpi.h>
6e2340276SBjoern A. Zeeb #include <linux/uuid.h>
7e2340276SBjoern A. Zeeb 
8e2340276SBjoern A. Zeeb #include "acpi.h"
9e2340276SBjoern A. Zeeb #include "debug.h"
10e2340276SBjoern A. Zeeb 
11e2340276SBjoern A. Zeeb #if defined(__linux__)
12e2340276SBjoern A. Zeeb static const guid_t rtw89_guid = GUID_INIT(0xD2A8C3E8, 0x4B69, 0x4F00,
13e2340276SBjoern A. Zeeb 					   0x82, 0xBD, 0xFE, 0x86,
14e2340276SBjoern A. Zeeb 					   0x07, 0x80, 0x3A, 0xA7);
15e2340276SBjoern A. Zeeb 
16*6d67aabdSBjoern A. Zeeb static
17*6d67aabdSBjoern A. Zeeb int rtw89_acpi_dsm_get_value(struct rtw89_dev *rtwdev, union acpi_object *obj,
18e2340276SBjoern A. Zeeb 			     u8 *value)
19e2340276SBjoern A. Zeeb {
20*6d67aabdSBjoern A. Zeeb 	if (obj->type != ACPI_TYPE_INTEGER) {
21*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_ACPI,
22*6d67aabdSBjoern A. Zeeb 			    "acpi: expect integer but type: %d\n", obj->type);
23e2340276SBjoern A. Zeeb 		return -EINVAL;
24e2340276SBjoern A. Zeeb 	}
25e2340276SBjoern A. Zeeb 
26*6d67aabdSBjoern A. Zeeb 	*value = (u8)obj->integer.value;
27*6d67aabdSBjoern A. Zeeb 	return 0;
28*6d67aabdSBjoern A. Zeeb }
29*6d67aabdSBjoern A. Zeeb 
30*6d67aabdSBjoern A. Zeeb static bool chk_acpi_policy_6ghz_sig(const struct rtw89_acpi_policy_6ghz *p)
31*6d67aabdSBjoern A. Zeeb {
32*6d67aabdSBjoern A. Zeeb 	return p->signature[0] == 0x00 &&
33*6d67aabdSBjoern A. Zeeb 	       p->signature[1] == 0xE0 &&
34*6d67aabdSBjoern A. Zeeb 	       p->signature[2] == 0x4C;
35*6d67aabdSBjoern A. Zeeb }
36*6d67aabdSBjoern A. Zeeb 
37*6d67aabdSBjoern A. Zeeb static
38*6d67aabdSBjoern A. Zeeb int rtw89_acpi_dsm_get_policy_6ghz(struct rtw89_dev *rtwdev,
39*6d67aabdSBjoern A. Zeeb 				   union acpi_object *obj,
40*6d67aabdSBjoern A. Zeeb 				   struct rtw89_acpi_policy_6ghz **policy_6ghz)
41*6d67aabdSBjoern A. Zeeb {
42*6d67aabdSBjoern A. Zeeb 	const struct rtw89_acpi_policy_6ghz *ptr;
43*6d67aabdSBjoern A. Zeeb 	u32 expect_len;
44*6d67aabdSBjoern A. Zeeb 	u32 len;
45*6d67aabdSBjoern A. Zeeb 
46*6d67aabdSBjoern A. Zeeb 	if (obj->type != ACPI_TYPE_BUFFER) {
47*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_ACPI,
48*6d67aabdSBjoern A. Zeeb 			    "acpi: expect buffer but type: %d\n", obj->type);
49*6d67aabdSBjoern A. Zeeb 		return -EINVAL;
50*6d67aabdSBjoern A. Zeeb 	}
51*6d67aabdSBjoern A. Zeeb 
52*6d67aabdSBjoern A. Zeeb 	len = obj->buffer.length;
53*6d67aabdSBjoern A. Zeeb 	if (len < sizeof(*ptr)) {
54*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: invalid buffer length: %u\n",
55*6d67aabdSBjoern A. Zeeb 			    __func__, len);
56*6d67aabdSBjoern A. Zeeb 		return -EINVAL;
57*6d67aabdSBjoern A. Zeeb 	}
58*6d67aabdSBjoern A. Zeeb 
59*6d67aabdSBjoern A. Zeeb 	ptr = (typeof(ptr))obj->buffer.pointer;
60*6d67aabdSBjoern A. Zeeb 	if (!chk_acpi_policy_6ghz_sig(ptr)) {
61*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: bad signature\n", __func__);
62*6d67aabdSBjoern A. Zeeb 		return -EINVAL;
63*6d67aabdSBjoern A. Zeeb 	}
64*6d67aabdSBjoern A. Zeeb 
65*6d67aabdSBjoern A. Zeeb 	expect_len = struct_size(ptr, country_list, ptr->country_count);
66*6d67aabdSBjoern A. Zeeb 	if (len < expect_len) {
67*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: expect %u but length: %u\n",
68*6d67aabdSBjoern A. Zeeb 			    __func__, expect_len, len);
69*6d67aabdSBjoern A. Zeeb 		return -EINVAL;
70*6d67aabdSBjoern A. Zeeb 	}
71*6d67aabdSBjoern A. Zeeb 
72*6d67aabdSBjoern A. Zeeb 	*policy_6ghz = kmemdup(ptr, expect_len, GFP_KERNEL);
73*6d67aabdSBjoern A. Zeeb 	if (!*policy_6ghz)
74*6d67aabdSBjoern A. Zeeb 		return -ENOMEM;
75*6d67aabdSBjoern A. Zeeb 
76*6d67aabdSBjoern A. Zeeb 	rtw89_hex_dump(rtwdev, RTW89_DBG_ACPI, "policy_6ghz: ", *policy_6ghz,
77*6d67aabdSBjoern A. Zeeb 		       expect_len);
78*6d67aabdSBjoern A. Zeeb 	return 0;
79*6d67aabdSBjoern A. Zeeb }
80*6d67aabdSBjoern A. Zeeb 
81*6d67aabdSBjoern A. Zeeb static bool chk_acpi_policy_6ghz_sp_sig(const struct rtw89_acpi_policy_6ghz_sp *p)
82*6d67aabdSBjoern A. Zeeb {
83*6d67aabdSBjoern A. Zeeb 	return p->signature[0] == 0x52 &&
84*6d67aabdSBjoern A. Zeeb 	       p->signature[1] == 0x54 &&
85*6d67aabdSBjoern A. Zeeb 	       p->signature[2] == 0x4B &&
86*6d67aabdSBjoern A. Zeeb 	       p->signature[3] == 0x07;
87*6d67aabdSBjoern A. Zeeb }
88*6d67aabdSBjoern A. Zeeb 
89*6d67aabdSBjoern A. Zeeb static
90*6d67aabdSBjoern A. Zeeb int rtw89_acpi_dsm_get_policy_6ghz_sp(struct rtw89_dev *rtwdev,
91*6d67aabdSBjoern A. Zeeb 				      union acpi_object *obj,
92*6d67aabdSBjoern A. Zeeb 				      struct rtw89_acpi_policy_6ghz_sp **policy)
93*6d67aabdSBjoern A. Zeeb {
94*6d67aabdSBjoern A. Zeeb 	const struct rtw89_acpi_policy_6ghz_sp *ptr;
95*6d67aabdSBjoern A. Zeeb 	u32 buf_len;
96*6d67aabdSBjoern A. Zeeb 
97*6d67aabdSBjoern A. Zeeb 	if (obj->type != ACPI_TYPE_BUFFER) {
98*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_ACPI,
99*6d67aabdSBjoern A. Zeeb 			    "acpi: expect buffer but type: %d\n", obj->type);
100*6d67aabdSBjoern A. Zeeb 		return -EINVAL;
101*6d67aabdSBjoern A. Zeeb 	}
102*6d67aabdSBjoern A. Zeeb 
103*6d67aabdSBjoern A. Zeeb 	buf_len = obj->buffer.length;
104*6d67aabdSBjoern A. Zeeb 	if (buf_len < sizeof(*ptr)) {
105*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: invalid buffer length: %u\n",
106*6d67aabdSBjoern A. Zeeb 			    __func__, buf_len);
107*6d67aabdSBjoern A. Zeeb 		return -EINVAL;
108*6d67aabdSBjoern A. Zeeb 	}
109*6d67aabdSBjoern A. Zeeb 
110*6d67aabdSBjoern A. Zeeb 	ptr = (typeof(ptr))obj->buffer.pointer;
111*6d67aabdSBjoern A. Zeeb 	if (!chk_acpi_policy_6ghz_sp_sig(ptr)) {
112*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: bad signature\n", __func__);
113*6d67aabdSBjoern A. Zeeb 		return -EINVAL;
114*6d67aabdSBjoern A. Zeeb 	}
115*6d67aabdSBjoern A. Zeeb 
116*6d67aabdSBjoern A. Zeeb 	*policy = kmemdup(ptr, sizeof(*ptr), GFP_KERNEL);
117*6d67aabdSBjoern A. Zeeb 	if (!*policy)
118*6d67aabdSBjoern A. Zeeb 		return -ENOMEM;
119*6d67aabdSBjoern A. Zeeb 
120*6d67aabdSBjoern A. Zeeb 	rtw89_hex_dump(rtwdev, RTW89_DBG_ACPI, "policy_6ghz_sp: ", *policy,
121*6d67aabdSBjoern A. Zeeb 		       sizeof(*ptr));
122e2340276SBjoern A. Zeeb 	return 0;
123e2340276SBjoern A. Zeeb }
124e2340276SBjoern A. Zeeb 
125e2340276SBjoern A. Zeeb int rtw89_acpi_evaluate_dsm(struct rtw89_dev *rtwdev,
126*6d67aabdSBjoern A. Zeeb 			    enum rtw89_acpi_dsm_func func,
127*6d67aabdSBjoern A. Zeeb 			    struct rtw89_acpi_dsm_result *res)
128e2340276SBjoern A. Zeeb {
129e2340276SBjoern A. Zeeb 	union acpi_object *obj;
130e2340276SBjoern A. Zeeb 	int ret;
131e2340276SBjoern A. Zeeb 
132e2340276SBjoern A. Zeeb 	obj = acpi_evaluate_dsm(ACPI_HANDLE(rtwdev->dev), &rtw89_guid,
133e2340276SBjoern A. Zeeb 				0, func, NULL);
134e2340276SBjoern A. Zeeb 	if (!obj) {
135*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_ACPI,
136e2340276SBjoern A. Zeeb 			    "acpi dsm fail to evaluate func: %d\n", func);
137e2340276SBjoern A. Zeeb 		return -ENOENT;
138e2340276SBjoern A. Zeeb 	}
139e2340276SBjoern A. Zeeb 
140*6d67aabdSBjoern A. Zeeb 	if (func == RTW89_ACPI_DSM_FUNC_6G_BP)
141*6d67aabdSBjoern A. Zeeb 		ret = rtw89_acpi_dsm_get_policy_6ghz(rtwdev, obj,
142*6d67aabdSBjoern A. Zeeb 						     &res->u.policy_6ghz);
143*6d67aabdSBjoern A. Zeeb 	else if (func == RTW89_ACPI_DSM_FUNC_6GHZ_SP_SUP)
144*6d67aabdSBjoern A. Zeeb 		ret = rtw89_acpi_dsm_get_policy_6ghz_sp(rtwdev, obj,
145*6d67aabdSBjoern A. Zeeb 							&res->u.policy_6ghz_sp);
146*6d67aabdSBjoern A. Zeeb 	else
147*6d67aabdSBjoern A. Zeeb 		ret = rtw89_acpi_dsm_get_value(rtwdev, obj, &res->u.value);
148e2340276SBjoern A. Zeeb 
149e2340276SBjoern A. Zeeb 	ACPI_FREE(obj);
150e2340276SBjoern A. Zeeb 	return ret;
151e2340276SBjoern A. Zeeb }
152e2340276SBjoern A. Zeeb #elif defined(__FreeBSD__)
153e2340276SBjoern A. Zeeb int rtw89_acpi_evaluate_dsm(struct rtw89_dev *rtwdev,
154*6d67aabdSBjoern A. Zeeb 			    enum rtw89_acpi_dsm_func func,
155*6d67aabdSBjoern A. Zeeb 			    struct rtw89_acpi_dsm_result *res)
156e2340276SBjoern A. Zeeb {
157e2340276SBjoern A. Zeeb 	return -ENOENT;
158e2340276SBjoern A. Zeeb }
159e2340276SBjoern A. Zeeb #endif
160