Skip to content

Commit 7cb06f0

Browse files
EvenxfJiri Kosina
authored andcommitted
HID: intel-thc-hid: intel-quickspi: Add THC QuickSPI ACPI interfaces
Add functions to query QuickSPI ACPI DSD parameters and provide APIs for DSM method accessing. Co-developed-by: Xinpeng Sun <[email protected]> Signed-off-by: Xinpeng Sun <[email protected]> Signed-off-by: Even Xu <[email protected]> Tested-by: Rui Zhang <[email protected]> Tested-by: Mark Pearson <[email protected]> Reviewed-by: Srinivas Pandruvada <[email protected]> Reviewed-by: Mark Pearson <[email protected]> Tested-by: Aaron Ma <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent 4751113 commit 7cb06f0

File tree

2 files changed

+243
-0
lines changed

2 files changed

+243
-0
lines changed

drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
/* SPDX-License-Identifier: GPL-2.0 */
22
/* Copyright (c) 2024 Intel Corporation */
33

4+
#include <linux/acpi.h>
5+
#include <linux/bitfield.h>
46
#include <linux/device.h>
57
#include <linux/dma-mapping.h>
68
#include <linux/err.h>
@@ -9,6 +11,7 @@
911
#include <linux/pci.h>
1012

1113
#include "intel-thc-dev.h"
14+
#include "intel-thc-hw.h"
1215

1316
#include "quickspi-dev.h"
1417

@@ -24,6 +27,186 @@ struct quickspi_driver_data ptl = {
2427
.max_packet_size_value = MAX_PACKET_SIZE_VALUE_LNL,
2528
};
2629

30+
/* THC QuickSPI ACPI method to get device properties */
31+
/* HIDSPI Method: {6e2ac436-0fcf-41af-a265-b32a220dcfab} */
32+
static guid_t hidspi_guid =
33+
GUID_INIT(0x6e2ac436, 0x0fcf, 0x41af, 0xa2, 0x65, 0xb3, 0x2a,
34+
0x22, 0x0d, 0xcf, 0xab);
35+
36+
/* QuickSpi Method: {300D35b7-ac20-413e-8e9c-92e4dafd0afe} */
37+
static guid_t thc_quickspi_guid =
38+
GUID_INIT(0x300d35b7, 0xac20, 0x413e, 0x8e, 0x9c, 0x92, 0xe4,
39+
0xda, 0xfd, 0x0a, 0xfe);
40+
41+
/* Platform Method: {84005682-5b71-41a4-0x8d668130f787a138} */
42+
static guid_t thc_platform_guid =
43+
GUID_INIT(0x84005682, 0x5b71, 0x41a4, 0x8d, 0x66, 0x81, 0x30,
44+
0xf7, 0x87, 0xa1, 0x38);
45+
46+
/**
47+
* thc_acpi_get_property - Query device ACPI parameter
48+
*
49+
* @adev: point to ACPI device
50+
* @guid: ACPI method's guid
51+
* @rev: ACPI method's revision
52+
* @func: ACPI method's function number
53+
* @type: ACPI parameter's data type
54+
* @prop_buf: point to return buffer
55+
*
56+
* This is a helper function for device to query its ACPI parameters.
57+
*
58+
* Return: 0 if successful or ENODEV on failed.
59+
*/
60+
static int thc_acpi_get_property(struct acpi_device *adev, const guid_t *guid,
61+
u64 rev, u64 func, acpi_object_type type, void *prop_buf)
62+
{
63+
acpi_handle handle = acpi_device_handle(adev);
64+
union acpi_object *obj;
65+
66+
obj = acpi_evaluate_dsm_typed(handle, guid, rev, func, NULL, type);
67+
if (!obj) {
68+
acpi_handle_err(handle,
69+
"Error _DSM call failed, rev: %llu, func: %llu, type: %u\n",
70+
rev, func, type);
71+
return -ENODEV;
72+
}
73+
74+
if (type == ACPI_TYPE_INTEGER)
75+
*(u32 *)prop_buf = (u32)obj->integer.value;
76+
else if (type == ACPI_TYPE_BUFFER)
77+
memcpy(prop_buf, obj->buffer.pointer, obj->buffer.length);
78+
79+
ACPI_FREE(obj);
80+
81+
return 0;
82+
}
83+
84+
/**
85+
* quickspi_get_acpi_resources - Query all quickspi devices' ACPI parameters
86+
*
87+
* @qsdev: point to quickspi device
88+
*
89+
* This function gets all quickspi devices' ACPI resource.
90+
*
91+
* Return: 0 if successful or error code on failed.
92+
*/
93+
static int quickspi_get_acpi_resources(struct quickspi_device *qsdev)
94+
{
95+
struct acpi_device *adev = ACPI_COMPANION(qsdev->dev);
96+
int ret = -EINVAL;
97+
98+
if (!adev) {
99+
dev_err(qsdev->dev, "no valid ACPI companion\n");
100+
return ret;
101+
}
102+
103+
qsdev->acpi_dev = adev;
104+
105+
ret = thc_acpi_get_property(adev, &hidspi_guid,
106+
ACPI_QUICKSPI_REVISION_NUM,
107+
ACPI_QUICKSPI_FUNC_NUM_INPUT_REP_HDR_ADDR,
108+
ACPI_TYPE_INTEGER,
109+
&qsdev->input_report_hdr_addr);
110+
if (ret)
111+
return ret;
112+
113+
ret = thc_acpi_get_property(adev, &hidspi_guid,
114+
ACPI_QUICKSPI_REVISION_NUM,
115+
ACPI_QUICKSPI_FUNC_NUM_INPUT_REP_BDY_ADDR,
116+
ACPI_TYPE_INTEGER,
117+
&qsdev->input_report_bdy_addr);
118+
if (ret)
119+
return ret;
120+
121+
ret = thc_acpi_get_property(adev, &hidspi_guid,
122+
ACPI_QUICKSPI_REVISION_NUM,
123+
ACPI_QUICKSPI_FUNC_NUM_OUTPUT_REP_ADDR,
124+
ACPI_TYPE_INTEGER,
125+
&qsdev->output_report_addr);
126+
if (ret)
127+
return ret;
128+
129+
ret = thc_acpi_get_property(adev, &hidspi_guid,
130+
ACPI_QUICKSPI_REVISION_NUM,
131+
ACPI_QUICKSPI_FUNC_NUM_READ_OPCODE,
132+
ACPI_TYPE_BUFFER,
133+
&qsdev->spi_read_opcode);
134+
if (ret)
135+
return ret;
136+
137+
ret = thc_acpi_get_property(adev, &hidspi_guid,
138+
ACPI_QUICKSPI_REVISION_NUM,
139+
ACPI_QUICKSPI_FUNC_NUM_WRITE_OPCODE,
140+
ACPI_TYPE_BUFFER,
141+
&qsdev->spi_write_opcode);
142+
if (ret)
143+
return ret;
144+
145+
ret = thc_acpi_get_property(adev, &hidspi_guid,
146+
ACPI_QUICKSPI_REVISION_NUM,
147+
ACPI_QUICKSPI_FUNC_NUM_IO_MODE,
148+
ACPI_TYPE_INTEGER,
149+
&qsdev->spi_read_io_mode);
150+
if (ret)
151+
return ret;
152+
153+
if (qsdev->spi_read_io_mode & SPI_WRITE_IO_MODE)
154+
qsdev->spi_write_io_mode = FIELD_GET(SPI_IO_MODE_OPCODE, qsdev->spi_read_io_mode);
155+
else
156+
qsdev->spi_write_io_mode = THC_SINGLE_IO;
157+
158+
qsdev->spi_read_io_mode = FIELD_GET(SPI_IO_MODE_OPCODE, qsdev->spi_read_io_mode);
159+
160+
ret = thc_acpi_get_property(adev, &thc_quickspi_guid,
161+
ACPI_QUICKSPI_REVISION_NUM,
162+
ACPI_QUICKSPI_FUNC_NUM_CONNECTION_SPEED,
163+
ACPI_TYPE_INTEGER,
164+
&qsdev->spi_freq_val);
165+
if (ret)
166+
return ret;
167+
168+
ret = thc_acpi_get_property(adev, &thc_quickspi_guid,
169+
ACPI_QUICKSPI_REVISION_NUM,
170+
ACPI_QUICKSPI_FUNC_NUM_LIMIT_PACKET_SIZE,
171+
ACPI_TYPE_INTEGER,
172+
&qsdev->limit_packet_size);
173+
if (ret)
174+
return ret;
175+
176+
if (qsdev->limit_packet_size || !qsdev->driver_data)
177+
qsdev->spi_packet_size = DEFAULT_MIN_PACKET_SIZE_VALUE;
178+
else
179+
qsdev->spi_packet_size = qsdev->driver_data->max_packet_size_value;
180+
181+
ret = thc_acpi_get_property(adev, &thc_quickspi_guid,
182+
ACPI_QUICKSPI_REVISION_NUM,
183+
ACPI_QUICKSPI_FUNC_NUM_PERFORMANCE_LIMIT,
184+
ACPI_TYPE_INTEGER,
185+
&qsdev->performance_limit);
186+
if (ret)
187+
return ret;
188+
189+
qsdev->performance_limit = FIELD_GET(PERFORMANCE_LIMITATION, qsdev->performance_limit);
190+
191+
ret = thc_acpi_get_property(adev, &thc_platform_guid,
192+
ACPI_QUICKSPI_REVISION_NUM,
193+
ACPI_QUICKSPI_FUNC_NUM_ACTIVE_LTR,
194+
ACPI_TYPE_INTEGER,
195+
&qsdev->active_ltr_val);
196+
if (ret)
197+
return ret;
198+
199+
ret = thc_acpi_get_property(adev, &thc_platform_guid,
200+
ACPI_QUICKSPI_REVISION_NUM,
201+
ACPI_QUICKSPI_FUNC_NUM_LP_LTR,
202+
ACPI_TYPE_INTEGER,
203+
&qsdev->low_power_ltr_val);
204+
if (ret)
205+
return ret;
206+
207+
return 0;
208+
}
209+
27210
/**
28211
* quickspi_irq_quick_handler - The ISR of the quickspi driver
29212
*
@@ -113,6 +296,12 @@ static struct quickspi_device *quickspi_dev_init(struct pci_dev *pdev, void __io
113296
return ERR_PTR(ret);
114297
}
115298

299+
ret = quickspi_get_acpi_resources(qsdev);
300+
if (ret) {
301+
dev_err(dev, "Get ACPI resources failed, ret = %d\n", ret);
302+
return ERR_PTR(ret);
303+
}
304+
116305
thc_interrupt_config(qsdev->thc_hw);
117306

118307
thc_interrupt_enable(qsdev->thc_hw, true);

drivers/hid/intel-thc-hid/intel-quickspi/quickspi-dev.h

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,28 @@
1515
#define PCI_DEVICE_ID_INTEL_THC_PTL_U_DEVICE_ID_SPI_PORT1 0xE449
1616
#define PCI_DEVICE_ID_INTEL_THC_PTL_U_DEVICE_ID_SPI_PORT2 0xE44B
1717

18+
/* HIDSPI special ACPI parameters DSM methods */
19+
#define ACPI_QUICKSPI_REVISION_NUM 2
20+
#define ACPI_QUICKSPI_FUNC_NUM_INPUT_REP_HDR_ADDR 1
21+
#define ACPI_QUICKSPI_FUNC_NUM_INPUT_REP_BDY_ADDR 2
22+
#define ACPI_QUICKSPI_FUNC_NUM_OUTPUT_REP_ADDR 3
23+
#define ACPI_QUICKSPI_FUNC_NUM_READ_OPCODE 4
24+
#define ACPI_QUICKSPI_FUNC_NUM_WRITE_OPCODE 5
25+
#define ACPI_QUICKSPI_FUNC_NUM_IO_MODE 6
26+
27+
/* QickSPI device special ACPI parameters DSM methods */
28+
#define ACPI_QUICKSPI_FUNC_NUM_CONNECTION_SPEED 1
29+
#define ACPI_QUICKSPI_FUNC_NUM_LIMIT_PACKET_SIZE 2
30+
#define ACPI_QUICKSPI_FUNC_NUM_PERFORMANCE_LIMIT 3
31+
32+
/* Platform special ACPI parameters DSM methods */
33+
#define ACPI_QUICKSPI_FUNC_NUM_ACTIVE_LTR 1
34+
#define ACPI_QUICKSPI_FUNC_NUM_LP_LTR 2
35+
36+
#define SPI_WRITE_IO_MODE BIT(13)
37+
#define SPI_IO_MODE_OPCODE GENMASK(15, 14)
38+
#define PERFORMANCE_LIMITATION GENMASK(15, 0)
39+
1840
/* Packet size value, the unit is 16 bytes */
1941
#define DEFAULT_MIN_PACKET_SIZE_VALUE 4
2042
#define MAX_PACKET_SIZE_VALUE_MTL 128
@@ -41,30 +63,62 @@ struct device;
4163
struct pci_dev;
4264
struct thc_device;
4365
struct hid_device;
66+
struct acpi_device;
4467

4568
/**
4669
* struct quickspi_device - THC QuickSpi device struct
4770
* @dev: point to kernel device
4871
* @pdev: point to PCI device
4972
* @thc_hw: point to THC device
5073
* @hid_dev: point to hid device
74+
* @acpi_dev: point to ACPI device
5175
* @driver_data: point to quickspi specific driver data
5276
* @state: THC SPI device state
5377
* @mem_addr: MMIO memory address
5478
* @dev_desc: device descriptor for HIDSPI protocol
79+
* @input_report_hdr_addr: device input report header address
80+
* @input_report_bdy_addr: device input report body address
81+
* @output_report_bdy_addr: device output report address
82+
* @spi_freq_val: device supported max SPI frequnecy, in Hz
83+
* @spi_read_io_mode: device supported SPI read io mode
84+
* @spi_write_io_mode: device supported SPI write io mode
85+
* @spi_read_opcode: device read opcode
86+
* @spi_write_opcode: device write opcode
87+
* @limit_packet_size: 1 - limit read/write packet to 64Bytes
88+
* 0 - device no packet size limiation for read/write
89+
* @performance_limit: delay time, in ms.
90+
* if device has performance limitation, must give a delay
91+
* before write operation after a read operation.
92+
* @active_ltr_val: THC active LTR value
93+
* @low_power_ltr_val: THC low power LTR value
5594
* @report_descriptor: store a copy of device report descriptor
5695
*/
5796
struct quickspi_device {
5897
struct device *dev;
5998
struct pci_dev *pdev;
6099
struct thc_device *thc_hw;
61100
struct hid_device *hid_dev;
101+
struct acpi_device *acpi_dev;
62102
struct quickspi_driver_data *driver_data;
63103
enum quickspi_dev_state state;
64104

65105
void __iomem *mem_addr;
66106

67107
struct hidspi_dev_descriptor dev_desc;
108+
u32 input_report_hdr_addr;
109+
u32 input_report_bdy_addr;
110+
u32 output_report_addr;
111+
u32 spi_freq_val;
112+
u32 spi_read_io_mode;
113+
u32 spi_write_io_mode;
114+
u32 spi_read_opcode;
115+
u32 spi_write_opcode;
116+
u32 limit_packet_size;
117+
u32 spi_packet_size;
118+
u32 performance_limit;
119+
120+
u32 active_ltr_val;
121+
u32 low_power_ltr_val;
68122

69123
u8 *report_descriptor;
70124
};

0 commit comments

Comments
 (0)