1 /*
2  * Copyright (c) 2023 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <errno.h>
8 #include <zephyr/acpi/acpi.h>
9 #include "soc.h"
10 #include "soc_gpio.h"
11 
12 #define GET_GPIO_BASE_NUM ("\\_SB.GINF")
13 
gpio_info_acpi_get(uint32_t bank_idx,uint32_t field_idx,uint32_t * ret_val)14 static int gpio_info_acpi_get(uint32_t bank_idx, uint32_t field_idx, uint32_t *ret_val)
15 {
16 	int status;
17 	ACPI_OBJECT args[2];
18 	ACPI_OBJECT_LIST arg_list;
19 	ACPI_OBJECT gpio_obj;
20 
21 	arg_list.Count = ARRAY_SIZE(args);
22 	arg_list.Pointer = args;
23 
24 	args[0].Type = ACPI_TYPE_INTEGER;
25 	args[0].Integer.Value = bank_idx;
26 
27 	args[1].Type = ACPI_TYPE_INTEGER;
28 	args[1].Integer.Value = field_idx;
29 
30 	status = acpi_invoke_method(GET_GPIO_BASE_NUM, &arg_list, &gpio_obj);
31 	if (status) {
32 		return status;
33 	}
34 
35 	if (gpio_obj.Type == ACPI_TYPE_INTEGER) {
36 		*ret_val = gpio_obj.Integer.Value;
37 	}
38 
39 	return status;
40 }
41 
soc_acpi_gpio_resource_get(int bank_idx,char * hid,char * uid,struct gpio_acpi_res * res)42 int soc_acpi_gpio_resource_get(int bank_idx, char *hid, char *uid, struct gpio_acpi_res *res)
43 {
44 	int ret;
45 	struct acpi_dev *acpi_child;
46 	struct acpi_irq_resource irq_res;
47 	struct acpi_mmio_resource mmio_res;
48 	uint32_t field_val[7];
49 	uint16_t irqs[CONFIG_ACPI_IRQ_VECTOR_MAX];
50 	struct acpi_reg_base reg_base[CONFIG_ACPI_MMIO_ENTRIES_MAX];
51 
52 	acpi_child = acpi_device_get(hid, uid);
53 	if (!acpi_child) {
54 		printk("acpi_device_get failed\n");
55 		return -EIO;
56 	}
57 
58 	mmio_res.mmio_max = ARRAY_SIZE(reg_base);
59 	mmio_res.reg_base = reg_base;
60 	ret = acpi_device_mmio_get(acpi_child, &mmio_res);
61 	if (ret) {
62 		printk("acpi_device_mmio_get failed\n");
63 		return ret;
64 	}
65 
66 	irq_res.irq_vector_max = ARRAY_SIZE(irqs);
67 	irq_res.irqs = irqs;
68 	ret = acpi_device_irq_get(acpi_child, &irq_res);
69 	if (ret) {
70 		printk("acpi_device_irq_get failed\n");
71 		return ret;
72 	}
73 
74 	res->irq = irq_res.irqs[0];
75 	res->irq_flags = irq_res.flags;
76 
77 	if (ACPI_RESOURCE_TYPE_GET(&mmio_res) == ACPI_RES_TYPE_MEM) {
78 		for (int i = 0; i < ARRAY_SIZE(field_val); i++) {
79 			ret = gpio_info_acpi_get(bank_idx, i, &field_val[i]);
80 			if (ret) {
81 				printk("gpio_info_acpi_get failed\n");
82 				return ret;
83 			}
84 		}
85 
86 		res->reg_base = ACPI_MMIO_GET(&mmio_res) & (~0x0FFFFFF);
87 		res->reg_base += field_val[0];
88 		res->len = ACPI_RESOURCE_SIZE_GET(&mmio_res);
89 		res->num_pins = field_val[1];
90 		res->pad_base = field_val[2];
91 		res->host_owner_reg = field_val[3];
92 		res->pad_owner_reg = field_val[4];
93 		res->intr_stat_reg = field_val[5] - 0x40;
94 		res->base_num = field_val[6];
95 	} else {
96 		printk("ACPI_RES_TYPE_MEM failed\n");
97 		return -ENODEV;
98 	}
99 
100 	return 0;
101 }
102