xref: /wlan-dirver/qca-wifi-host-cmn/wmi/src/wmi_unified_gpio_tlv.c (revision 2f4b444fb7e689b83a4ab0e7b3b38f0bf4def8e0)
1 /*
2  * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #include <osdep.h>
18 #include <wmi.h>
19 #include <wmi_unified_priv.h>
20 #include <wmi_unified_gpio_api.h>
21 
22 /**
23  * convert_gpio_dir() - Function to convert unified gpio direction
24  * @dir: pointer to enum gpio_direction
25  *
26  * Convert the wmi unified gpio direction to FW TLV WMI gpio direction
27  *
28  * Return:
29  * 0 - Output
30  * 1 - Input
31  */
32 static uint32_t
33 convert_gpio_direction(enum gpio_direction dir)
34 {
35 	switch (dir) {
36 	case WMI_HOST_GPIO_INPUT:
37 		return WMI_FW_GPIO_INPUT;
38 	case WMI_HOST_GPIO_OUTPUT:
39 		return WMI_FW_GPIO_OUTPUT;
40 	default:
41 		return WMI_FW_GPIO_OUTPUT;
42 	}
43 }
44 
45 /**
46  * convert_gpio_pull_type() - Function to convert unified pull type
47  * @pull_type: pointer to enum gpio_pull_type
48  *
49  * Convert the wmi unified pull type to FW TLV WMI gpio pull type
50  *
51  * Return: FW TLV WMI gpio pull type
52  */
53 static uint32_t
54 convert_gpio_pull_type(enum gpio_pull_type pull_type)
55 {
56 	switch (pull_type) {
57 	case WMI_HOST_GPIO_PULL_NONE:
58 		return WMI_GPIO_PULL_NONE;
59 	case WMI_HOST_GPIO_PULL_UP:
60 		return WMI_GPIO_PULL_UP;
61 	case WMI_HOST_GPIO_PULL_DOWN:
62 		return WMI_GPIO_PULL_DOWN;
63 	default:
64 		return WMI_GPIO_PULL_NONE;
65 	}
66 }
67 
68 /**
69  * convert_gpio_interrupt_mode() - Function to convert unified interrupt mode
70  * @intr_mode: pointer to enum gpio_interrupt_mode
71  *
72  * Convert the wmi unified interrupt mode to FW TLV WMI gpio interrupt mode
73  *
74  * Return: FW TLV WMI gpio interrupt mode
75  */
76 static uint32_t
77 convert_gpio_interrupt_mode(enum gpio_interrupt_mode intr_mode)
78 {
79 	switch (intr_mode) {
80 	case WMI_HOST_GPIO_INTMODE_DISABLE:
81 		return WMI_GPIO_INTTYPE_DISABLE;
82 	case WMI_HOST_GPIO_INTMODE_RISING_EDGE:
83 		return WMI_GPIO_INTTYPE_RISING_EDGE;
84 	case WMI_HOST_GPIO_INTMODE_FALLING_EDGE:
85 		return WMI_GPIO_INTTYPE_FALLING_EDGE;
86 	case WMI_HOST_GPIO_INTMODE_BOTH_EDGE:
87 		return WMI_GPIO_INTTYPE_BOTH_EDGE;
88 	case WMI_HOST_GPIO_INTMODE_LEVEL_LOW:
89 		return WMI_GPIO_INTTYPE_LEVEL_LOW;
90 	case WMI_HOST_GPIO_INTMODE_LEVEL_HIGH:
91 		return WMI_GPIO_INTTYPE_LEVEL_HIGH;
92 	default:
93 		return WMI_GPIO_INTTYPE_DISABLE;
94 	}
95 }
96 
97 /**
98  * convert_gpio_output_value() - Function to convert unified gpio output value
99  * @value: pointer to enum gpio_value
100  *
101  * Convert the wmi unified gpio output value to FW TLV WMI gpio output value
102  *
103  * Return:
104  * 0 - Output low level
105  * 1 - Output high level
106  */
107 static uint32_t
108 convert_gpio_output_value(enum gpio_value value)
109 {
110 	switch (value) {
111 	case WMI_HOST_GPIO_LEVEL_LOW:
112 		return 0;
113 	case WMI_HOST_GPIO_LEVEL_HIGH:
114 		return 1;
115 	default:
116 		return 0;
117 	}
118 }
119 
120 /**
121  * send_gpio_config_cmd_tlv() - send gpio config to fw
122  * @wmi_handle: wmi handle
123  * @param: pointer to hold gpio config params
124  *
125  * Send gpio configuration to firmware.
126  *
127  * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure
128  */
129 static QDF_STATUS
130 send_gpio_config_cmd_tlv(wmi_unified_t wmi_handle,
131 			 struct gpio_config_params *param)
132 {
133 	wmi_gpio_config_cmd_fixed_param *cmd;
134 	wmi_buf_t buf;
135 	int32_t len;
136 	QDF_STATUS ret;
137 
138 	len = sizeof(*cmd);
139 
140 	/* Sanity Checks */
141 	if (param->pin_pull_type >= WMI_HOST_GPIO_PULL_MAX ||
142 	    param->pin_intr_mode >= WMI_HOST_GPIO_INTMODE_MAX ||
143 	    param->pin_dir >= WMI_HOST_GPIO_DIR_MAX) {
144 		return QDF_STATUS_E_FAILURE;
145 	}
146 
147 	buf = wmi_buf_alloc(wmi_handle, len);
148 	if (!buf)
149 		return QDF_STATUS_E_FAILURE;
150 
151 	cmd = (wmi_gpio_config_cmd_fixed_param *)wmi_buf_data(buf);
152 	WMITLV_SET_HDR(&cmd->tlv_header,
153 		       WMITLV_TAG_STRUC_wmi_gpio_config_cmd_fixed_param,
154 		       WMITLV_GET_STRUCT_TLVLEN(
155 				wmi_gpio_config_cmd_fixed_param));
156 	cmd->gpio_num = param->pin_num;
157 	cmd->input = convert_gpio_direction(param->pin_dir);
158 	cmd->pull_type = convert_gpio_pull_type(param->pin_pull_type);
159 	cmd->intr_mode = convert_gpio_interrupt_mode(param->pin_intr_mode);
160 	cmd->mux_config_val = param->mux_config_val;
161 	cmd->drive = param->drive;
162 	cmd->init_enable = param->init_enable;
163 
164 	wmi_debug("GPIO num %d, input-dir %d, pull_type %d, intr_mode %d"
165 		 " mux_config_val %d drive %d init_enable %d",
166 		 cmd->gpio_num, cmd->input, cmd->pull_type, cmd->intr_mode,
167 		 cmd->mux_config_val, cmd->drive, cmd->init_enable);
168 
169 	wmi_mtrace(WMI_GPIO_CONFIG_CMDID, NO_SESSION, 0);
170 	ret = wmi_unified_cmd_send(wmi_handle, buf, sizeof(*cmd),
171 				   WMI_GPIO_CONFIG_CMDID);
172 
173 	if (QDF_IS_STATUS_ERROR(ret)) {
174 		wmi_err("Sending GPIO config cmd failed");
175 		wmi_buf_free(buf);
176 	}
177 
178 	return ret;
179 }
180 
181 /**
182  * send_gpio_output_cmd_tlv() - send gpio output to fw
183  * @wmi_handle: wmi handle
184  * @param: pointer to hold gpio output param
185  *
186  * Send gpio output value to firmware.
187  *
188  * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure
189  */
190 static QDF_STATUS
191 send_gpio_output_cmd_tlv(wmi_unified_t wmi_handle,
192 			 struct gpio_output_params *param)
193 {
194 	wmi_gpio_output_cmd_fixed_param *cmd;
195 	wmi_buf_t buf;
196 	int32_t len;
197 	QDF_STATUS ret;
198 
199 	len = sizeof(*cmd);
200 
201 	/* Sanity Checks */
202 	if (param->pin_set >= WMI_HOST_GPIO_LEVEL_MAX)
203 		return QDF_STATUS_E_FAILURE;
204 
205 	buf = wmi_buf_alloc(wmi_handle, len);
206 	if (!buf)
207 		return QDF_STATUS_E_FAILURE;
208 
209 	cmd = (wmi_gpio_output_cmd_fixed_param *)wmi_buf_data(buf);
210 	WMITLV_SET_HDR(&cmd->tlv_header,
211 		       WMITLV_TAG_STRUC_wmi_gpio_output_cmd_fixed_param,
212 		       WMITLV_GET_STRUCT_TLVLEN(
213 				wmi_gpio_output_cmd_fixed_param));
214 	cmd->gpio_num = param->pin_num;
215 	cmd->set = convert_gpio_output_value(param->pin_set);
216 
217 	wmi_debug("GPIO num %d, set %d", cmd->gpio_num, cmd->set);
218 	wmi_mtrace(WMI_GPIO_OUTPUT_CMDID, NO_SESSION, 0);
219 	ret = wmi_unified_cmd_send(wmi_handle, buf, sizeof(*cmd),
220 				   WMI_GPIO_OUTPUT_CMDID);
221 
222 	if (QDF_IS_STATUS_ERROR(ret)) {
223 		wmi_err("Sending GPIO output cmd failed");
224 		wmi_buf_free(buf);
225 	}
226 
227 	return ret;
228 }
229 
230 void wmi_gpio_attach_tlv(wmi_unified_t wmi_handle)
231 {
232 	struct wmi_ops *ops = wmi_handle->ops;
233 
234 	ops->send_gpio_config_cmd = send_gpio_config_cmd_tlv;
235 	ops->send_gpio_output_cmd = send_gpio_output_cmd_tlv;
236 }
237 
238