xref: /wlan-driver/qca-wifi-host-cmn/os_if/linux/gpio/src/wlan_cfg80211_gpio.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2020, The Linux Foundation. All rights reserved.
3*5113495bSYour Name  *
4*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for any
5*5113495bSYour Name  * purpose with or without fee is hereby granted, provided that the above
6*5113495bSYour Name  * copyright notice and this permission notice appear in all copies.
7*5113495bSYour Name  *
8*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9*5113495bSYour Name  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10*5113495bSYour Name  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11*5113495bSYour Name  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12*5113495bSYour Name  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13*5113495bSYour Name  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14*5113495bSYour Name  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15*5113495bSYour Name  */
16*5113495bSYour Name 
17*5113495bSYour Name /**
18*5113495bSYour Name  * DOC: defines driver functions interfacing with linux kernel
19*5113495bSYour Name  */
20*5113495bSYour Name 
21*5113495bSYour Name #include <qdf_list.h>
22*5113495bSYour Name #include <qdf_status.h>
23*5113495bSYour Name #include <linux/wireless.h>
24*5113495bSYour Name #include <linux/netdevice.h>
25*5113495bSYour Name #include <wlan_cfg80211.h>
26*5113495bSYour Name #include <wlan_osif_priv.h>
27*5113495bSYour Name #include <wlan_gpio_ucfg_api.h>
28*5113495bSYour Name #include <wlan_cfg80211_gpio.h>
29*5113495bSYour Name #include "qdf_module.h"
30*5113495bSYour Name 
31*5113495bSYour Name const struct nla_policy
32*5113495bSYour Name wlan_cfg80211_gpio_config_policy[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MAX + 1] = {
33*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND] = {
34*5113495bSYour Name 						.type = NLA_U32,
35*5113495bSYour Name 						.len = sizeof(uint32_t) },
36*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PINNUM] = {
37*5113495bSYour Name 						.type = NLA_U32,
38*5113495bSYour Name 						.len = sizeof(uint32_t) },
39*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_VALUE] = {
40*5113495bSYour Name 						.type = NLA_U32,
41*5113495bSYour Name 						.len = sizeof(uint32_t) },
42*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PULL_TYPE] = {
43*5113495bSYour Name 						.type = NLA_U32,
44*5113495bSYour Name 						.len = sizeof(uint32_t) },
45*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTR_MODE] = {
46*5113495bSYour Name 						.type = NLA_U32,
47*5113495bSYour Name 						.len = sizeof(uint32_t) },
48*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DIR] = {
49*5113495bSYour Name 						.type = NLA_U32,
50*5113495bSYour Name 						.len = sizeof(uint32_t) },
51*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MUX_CONFIG] = {
52*5113495bSYour Name 						.type = NLA_U32,
53*5113495bSYour Name 						.len = sizeof(uint32_t) },
54*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DRIVE] = {
55*5113495bSYour Name 						.type = NLA_U32,
56*5113495bSYour Name 						.len = sizeof(uint32_t) },
57*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG] = {
58*5113495bSYour Name 						.type = NLA_U32,
59*5113495bSYour Name 						.len = sizeof(uint32_t) },
60*5113495bSYour Name };
61*5113495bSYour Name 
62*5113495bSYour Name /**
63*5113495bSYour Name  * convert_vendor_gpio_direction() - Function to convert vendor gpio direction
64*5113495bSYour Name  * @dir: pointer to enum qca_gpio_direction
65*5113495bSYour Name  *
66*5113495bSYour Name  * Convert the vendor gpio direction to wmi unified gpio direction
67*5113495bSYour Name  *
68*5113495bSYour Name  * Return: wmi unified gpio direction
69*5113495bSYour Name  */
70*5113495bSYour Name static enum gpio_direction
convert_vendor_gpio_direction(enum qca_gpio_direction dir)71*5113495bSYour Name convert_vendor_gpio_direction(enum qca_gpio_direction dir)
72*5113495bSYour Name {
73*5113495bSYour Name 	switch (dir) {
74*5113495bSYour Name 	case QCA_WLAN_GPIO_INPUT:
75*5113495bSYour Name 		return WMI_HOST_GPIO_INPUT;
76*5113495bSYour Name 	case QCA_WLAN_GPIO_OUTPUT:
77*5113495bSYour Name 		return WMI_HOST_GPIO_OUTPUT;
78*5113495bSYour Name 	default:
79*5113495bSYour Name 		return WMI_HOST_GPIO_INPUT;
80*5113495bSYour Name 	}
81*5113495bSYour Name }
82*5113495bSYour Name 
83*5113495bSYour Name /**
84*5113495bSYour Name  * convert_vendor_gpio_pull_type() - Function to convert vendor pull type
85*5113495bSYour Name  * @pull_type: pointer to enum qca_gpio_pull_type
86*5113495bSYour Name  *
87*5113495bSYour Name  * Convert the vendor pull type to wmi unified pull type
88*5113495bSYour Name  *
89*5113495bSYour Name  * Return: wmi unified gpio pull type
90*5113495bSYour Name  */
91*5113495bSYour Name static enum gpio_pull_type
convert_vendor_gpio_pull_type(enum qca_gpio_pull_type pull_type)92*5113495bSYour Name convert_vendor_gpio_pull_type(enum qca_gpio_pull_type pull_type)
93*5113495bSYour Name {
94*5113495bSYour Name 	switch (pull_type) {
95*5113495bSYour Name 	case QCA_WLAN_GPIO_PULL_NONE:
96*5113495bSYour Name 		return WMI_HOST_GPIO_PULL_NONE;
97*5113495bSYour Name 	case QCA_WLAN_GPIO_PULL_UP:
98*5113495bSYour Name 		return WMI_HOST_GPIO_PULL_UP;
99*5113495bSYour Name 	case QCA_WLAN_GPIO_PULL_DOWN:
100*5113495bSYour Name 		return WMI_HOST_GPIO_PULL_DOWN;
101*5113495bSYour Name 	default:
102*5113495bSYour Name 		return WMI_HOST_GPIO_PULL_NONE;
103*5113495bSYour Name 	}
104*5113495bSYour Name }
105*5113495bSYour Name 
106*5113495bSYour Name /**
107*5113495bSYour Name  * convert_vendor_gpio_interrupt_mode() - Function to convert
108*5113495bSYour Name  * vendor interrupt mode
109*5113495bSYour Name  * @intr_mode: pointer to enum qca_gpio_interrupt_mode
110*5113495bSYour Name  *
111*5113495bSYour Name  * Convert the vendor interrupt mode to wmi unified interrupt mode
112*5113495bSYour Name  *
113*5113495bSYour Name  * Return: wmi unified gpio interrupt mode
114*5113495bSYour Name  */
115*5113495bSYour Name static enum gpio_interrupt_mode
convert_vendor_gpio_interrupt_mode(enum qca_gpio_interrupt_mode intr_mode)116*5113495bSYour Name convert_vendor_gpio_interrupt_mode(enum qca_gpio_interrupt_mode intr_mode)
117*5113495bSYour Name {
118*5113495bSYour Name 	switch (intr_mode) {
119*5113495bSYour Name 	case QCA_WLAN_GPIO_INTMODE_DISABLE:
120*5113495bSYour Name 		return WMI_HOST_GPIO_INTMODE_DISABLE;
121*5113495bSYour Name 	case QCA_WLAN_GPIO_INTMODE_RISING_EDGE:
122*5113495bSYour Name 		return WMI_HOST_GPIO_INTMODE_RISING_EDGE;
123*5113495bSYour Name 	case QCA_WLAN_GPIO_INTMODE_FALLING_EDGE:
124*5113495bSYour Name 		return WMI_HOST_GPIO_INTMODE_FALLING_EDGE;
125*5113495bSYour Name 	case QCA_WLAN_GPIO_INTMODE_BOTH_EDGE:
126*5113495bSYour Name 		return WMI_HOST_GPIO_INTMODE_BOTH_EDGE;
127*5113495bSYour Name 	case QCA_WLAN_GPIO_INTMODE_LEVEL_LOW:
128*5113495bSYour Name 		return WMI_HOST_GPIO_INTMODE_LEVEL_LOW;
129*5113495bSYour Name 	case QCA_WLAN_GPIO_INTMODE_LEVEL_HIGH:
130*5113495bSYour Name 		return WMI_HOST_GPIO_INTMODE_LEVEL_HIGH;
131*5113495bSYour Name 	default:
132*5113495bSYour Name 		return WMI_HOST_GPIO_INTMODE_DISABLE;
133*5113495bSYour Name 	}
134*5113495bSYour Name }
135*5113495bSYour Name 
136*5113495bSYour Name /**
137*5113495bSYour Name  * convert_vendor_gpio_output_value() - Function to convert vendor
138*5113495bSYour Name  * gpio output value
139*5113495bSYour Name  * @value: pointer to enum qca_gpio_value
140*5113495bSYour Name  *
141*5113495bSYour Name  * Convert the vendor gpio value to wmi unified gpio output value
142*5113495bSYour Name  *
143*5113495bSYour Name  * Return: wmi unified gpio output value
144*5113495bSYour Name  */
145*5113495bSYour Name static enum gpio_value
convert_vendor_gpio_output_value(enum qca_gpio_value value)146*5113495bSYour Name convert_vendor_gpio_output_value(enum qca_gpio_value value)
147*5113495bSYour Name {
148*5113495bSYour Name 	switch (value) {
149*5113495bSYour Name 	case QCA_WLAN_GPIO_LEVEL_LOW:
150*5113495bSYour Name 		return WMI_HOST_GPIO_LEVEL_LOW;
151*5113495bSYour Name 	case QCA_WLAN_GPIO_LEVEL_HIGH:
152*5113495bSYour Name 		return WMI_HOST_GPIO_LEVEL_HIGH;
153*5113495bSYour Name 	default:
154*5113495bSYour Name 		return WMI_HOST_GPIO_LEVEL_LOW;
155*5113495bSYour Name 	}
156*5113495bSYour Name }
157*5113495bSYour Name 
158*5113495bSYour Name /**
159*5113495bSYour Name  * convert_vendor_gpio_drive() - Function to convert vendor
160*5113495bSYour Name  * gpio drive
161*5113495bSYour Name  * @drive: value of enum gpio_drive
162*5113495bSYour Name  *
163*5113495bSYour Name  * Convert the vendor gpio drive to wmi unified gpio output drive
164*5113495bSYour Name  *
165*5113495bSYour Name  * Return: wmi unified gpio output drive config
166*5113495bSYour Name  */
167*5113495bSYour Name static enum gpio_drive
convert_vendor_gpio_drive(enum qca_gpio_drive drive)168*5113495bSYour Name convert_vendor_gpio_drive(enum qca_gpio_drive drive)
169*5113495bSYour Name {
170*5113495bSYour Name 	switch (drive) {
171*5113495bSYour Name 	case QCA_WLAN_GPIO_DRIVE_2MA:
172*5113495bSYour Name 		return WMI_HOST_GPIO_DRIVE_2MA;
173*5113495bSYour Name 	case QCA_WLAN_GPIO_DRIVE_4MA:
174*5113495bSYour Name 		return WMI_HOST_GPIO_DRIVE_4MA;
175*5113495bSYour Name 	case QCA_WLAN_GPIO_DRIVE_6MA:
176*5113495bSYour Name 		return WMI_HOST_GPIO_DRIVE_6MA;
177*5113495bSYour Name 	case QCA_WLAN_GPIO_DRIVE_8MA:
178*5113495bSYour Name 		return WMI_HOST_GPIO_DRIVE_8MA;
179*5113495bSYour Name 	case QCA_WLAN_GPIO_DRIVE_10MA:
180*5113495bSYour Name 		return WMI_HOST_GPIO_DRIVE_10MA;
181*5113495bSYour Name 	case QCA_WLAN_GPIO_DRIVE_12MA:
182*5113495bSYour Name 		return WMI_HOST_GPIO_DRIVE_12MA;
183*5113495bSYour Name 	case QCA_WLAN_GPIO_DRIVE_14MA:
184*5113495bSYour Name 		return WMI_HOST_GPIO_DRIVE_14MA;
185*5113495bSYour Name 	case QCA_WLAN_GPIO_DRIVE_16MA:
186*5113495bSYour Name 		return WMI_HOST_GPIO_DRIVE_16MA;
187*5113495bSYour Name 	default:
188*5113495bSYour Name 		return WMI_HOST_GPIO_DRIVE_2MA;
189*5113495bSYour Name 	}
190*5113495bSYour Name }
191*5113495bSYour Name 
192*5113495bSYour Name /**
193*5113495bSYour Name  * convert_vendor_gpio_init_enable() - Function to convert vendor
194*5113495bSYour Name  * gpio init_enable
195*5113495bSYour Name  * @internal_config: Param to decide whether to use internal config
196*5113495bSYour Name  *
197*5113495bSYour Name  * Convert the vendor internal_config to wmi unified gpio output init_enable
198*5113495bSYour Name  *
199*5113495bSYour Name  * Return: wmi unified gpio output init_enable config
200*5113495bSYour Name  */
201*5113495bSYour Name static enum gpio_init_enable
convert_vendor_gpio_init_enable(uint32_t internal_config)202*5113495bSYour Name convert_vendor_gpio_init_enable(uint32_t internal_config)
203*5113495bSYour Name {
204*5113495bSYour Name 	if(internal_config)
205*5113495bSYour Name 		return WMI_HOST_GPIO_INIT_DISABLE;
206*5113495bSYour Name 	else
207*5113495bSYour Name 		return WMI_HOST_GPIO_INIT_ENABLE;
208*5113495bSYour Name }
209*5113495bSYour Name 
210*5113495bSYour Name /**
211*5113495bSYour Name  * wlan_set_gpio_config() - set the gpio configuration info
212*5113495bSYour Name  * @psoc: the pointer of wlan_objmgr_psoc
213*5113495bSYour Name  * @attr: list of attributes
214*5113495bSYour Name  *
215*5113495bSYour Name  * Return: 0 on success; errno on failure
216*5113495bSYour Name  */
217*5113495bSYour Name static int
wlan_set_gpio_config(struct wlan_objmgr_psoc * psoc,struct nlattr ** attr)218*5113495bSYour Name wlan_set_gpio_config(struct wlan_objmgr_psoc *psoc,
219*5113495bSYour Name 		     struct nlattr **attr)
220*5113495bSYour Name {
221*5113495bSYour Name 	struct gpio_config_params cfg_param;
222*5113495bSYour Name 	struct nlattr *gpio_attr;
223*5113495bSYour Name 	enum qca_gpio_direction pin_dir;
224*5113495bSYour Name 	enum qca_gpio_pull_type pull_type;
225*5113495bSYour Name 	enum qca_gpio_interrupt_mode intr_mode;
226*5113495bSYour Name 	enum qca_gpio_drive drive;
227*5113495bSYour Name 	uint32_t internal_config;
228*5113495bSYour Name 	QDF_STATUS status;
229*5113495bSYour Name 
230*5113495bSYour Name 	gpio_attr = attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PINNUM];
231*5113495bSYour Name 	if (!gpio_attr) {
232*5113495bSYour Name 		osif_err_rl("attr gpio number failed");
233*5113495bSYour Name 		return -EINVAL;
234*5113495bSYour Name 	}
235*5113495bSYour Name 	cfg_param.pin_num = nla_get_u32(gpio_attr);
236*5113495bSYour Name 
237*5113495bSYour Name 	gpio_attr = attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DIR];
238*5113495bSYour Name 	if (!gpio_attr) {
239*5113495bSYour Name 		osif_err_rl("attr gpio dir failed");
240*5113495bSYour Name 		return -EINVAL;
241*5113495bSYour Name 	}
242*5113495bSYour Name 	pin_dir = nla_get_u32(gpio_attr);
243*5113495bSYour Name 	if (pin_dir >= QCA_WLAN_GPIO_DIR_MAX) {
244*5113495bSYour Name 		osif_err_rl("attr gpio direction invalid");
245*5113495bSYour Name 		return -EINVAL;
246*5113495bSYour Name 	}
247*5113495bSYour Name 	cfg_param.pin_dir = convert_vendor_gpio_direction(pin_dir);
248*5113495bSYour Name 
249*5113495bSYour Name 	gpio_attr = attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PULL_TYPE];
250*5113495bSYour Name 	if (!gpio_attr) {
251*5113495bSYour Name 		osif_err_rl("attr gpio pull failed");
252*5113495bSYour Name 		return -EINVAL;
253*5113495bSYour Name 	}
254*5113495bSYour Name 	pull_type = nla_get_u32(gpio_attr);
255*5113495bSYour Name 	if (pull_type >= QCA_WLAN_GPIO_PULL_MAX) {
256*5113495bSYour Name 		osif_err_rl("attr gpio pull type invalid");
257*5113495bSYour Name 		return -EINVAL;
258*5113495bSYour Name 	}
259*5113495bSYour Name 	cfg_param.pin_pull_type = convert_vendor_gpio_pull_type(pull_type);
260*5113495bSYour Name 
261*5113495bSYour Name 	gpio_attr = attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTR_MODE];
262*5113495bSYour Name 	if (!gpio_attr) {
263*5113495bSYour Name 		osif_err_rl("attr gpio interrupt mode failed");
264*5113495bSYour Name 		return -EINVAL;
265*5113495bSYour Name 	}
266*5113495bSYour Name 	intr_mode = nla_get_u32(gpio_attr);
267*5113495bSYour Name 	if (intr_mode >= QCA_WLAN_GPIO_INTMODE_MAX) {
268*5113495bSYour Name 		osif_err_rl("attr gpio interrupt mode invalid");
269*5113495bSYour Name 		return -EINVAL;
270*5113495bSYour Name 	}
271*5113495bSYour Name 	cfg_param.pin_intr_mode = convert_vendor_gpio_interrupt_mode(intr_mode);
272*5113495bSYour Name 
273*5113495bSYour Name 	/* Below are optional parameters. Initialize to zero */
274*5113495bSYour Name 	cfg_param.mux_config_val = WMI_HOST_GPIO_MUX_DEFAULT;
275*5113495bSYour Name 	cfg_param.drive = WMI_HOST_GPIO_DRIVE_2MA;
276*5113495bSYour Name 	cfg_param.init_enable = WMI_HOST_GPIO_INIT_DISABLE;
277*5113495bSYour Name 
278*5113495bSYour Name 	gpio_attr = attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MUX_CONFIG];
279*5113495bSYour Name 	if (gpio_attr) {
280*5113495bSYour Name 		cfg_param.mux_config_val = nla_get_u32(gpio_attr);
281*5113495bSYour Name 	}
282*5113495bSYour Name 
283*5113495bSYour Name 	gpio_attr = attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DRIVE];
284*5113495bSYour Name 	if (gpio_attr) {
285*5113495bSYour Name 		drive = nla_get_u32(gpio_attr);
286*5113495bSYour Name 		if (drive >= QCA_WLAN_GPIO_DRIVE_MAX) {
287*5113495bSYour Name 			osif_err_rl("attr gpio drive invalid");
288*5113495bSYour Name 			return -EINVAL;
289*5113495bSYour Name 		}
290*5113495bSYour Name 		cfg_param.drive = convert_vendor_gpio_drive(drive);
291*5113495bSYour Name 	}
292*5113495bSYour Name 
293*5113495bSYour Name 	gpio_attr = attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG];
294*5113495bSYour Name 	if (gpio_attr) {
295*5113495bSYour Name 		internal_config = nla_get_u32(gpio_attr);
296*5113495bSYour Name 		cfg_param.init_enable =
297*5113495bSYour Name 			convert_vendor_gpio_init_enable(internal_config);
298*5113495bSYour Name 	}
299*5113495bSYour Name 
300*5113495bSYour Name 	status = ucfg_set_gpio_config(psoc, &cfg_param);
301*5113495bSYour Name 	return status;
302*5113495bSYour Name }
303*5113495bSYour Name 
304*5113495bSYour Name /**
305*5113495bSYour Name  * wlan_set_gpio_output() - set the gpio output info
306*5113495bSYour Name  * @psoc: the pointer of wlan_objmgr_psoc
307*5113495bSYour Name  * @attr: list of attributes
308*5113495bSYour Name  *
309*5113495bSYour Name  * Return: 0 on success; errno on failure
310*5113495bSYour Name  */
311*5113495bSYour Name static int
wlan_set_gpio_output(struct wlan_objmgr_psoc * psoc,struct nlattr ** attr)312*5113495bSYour Name wlan_set_gpio_output(struct wlan_objmgr_psoc *psoc,
313*5113495bSYour Name 		     struct nlattr **attr)
314*5113495bSYour Name {
315*5113495bSYour Name 	struct gpio_output_params out_param;
316*5113495bSYour Name 	struct nlattr *gpio_attr;
317*5113495bSYour Name 	enum qca_gpio_value pin_set;
318*5113495bSYour Name 	QDF_STATUS status;
319*5113495bSYour Name 
320*5113495bSYour Name 	gpio_attr = attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PINNUM];
321*5113495bSYour Name 	if (!gpio_attr) {
322*5113495bSYour Name 		osif_err_rl("attr gpio number failed");
323*5113495bSYour Name 		return -EINVAL;
324*5113495bSYour Name 	}
325*5113495bSYour Name 	out_param.pin_num = nla_get_u32(gpio_attr);
326*5113495bSYour Name 
327*5113495bSYour Name 	gpio_attr = attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_VALUE];
328*5113495bSYour Name 	if (!gpio_attr) {
329*5113495bSYour Name 		osif_err_rl("attr gpio value failed");
330*5113495bSYour Name 		return -EINVAL;
331*5113495bSYour Name 	}
332*5113495bSYour Name 	pin_set = nla_get_u32(gpio_attr);
333*5113495bSYour Name 	if (pin_set >= QCA_WLAN_GPIO_LEVEL_MAX) {
334*5113495bSYour Name 		osif_err_rl("attr gpio level invalid");
335*5113495bSYour Name 		return -EINVAL;
336*5113495bSYour Name 	}
337*5113495bSYour Name 	out_param.pin_set = convert_vendor_gpio_output_value(pin_set);
338*5113495bSYour Name 
339*5113495bSYour Name 	status = ucfg_set_gpio_output(psoc, &out_param);
340*5113495bSYour Name 	return status;
341*5113495bSYour Name }
342*5113495bSYour Name 
343*5113495bSYour Name /**
344*5113495bSYour Name  * wlan_cfg80211_start_gpio_config - Set the gpio configuration
345*5113495bSYour Name  * @wiphy: pointer to wiphy
346*5113495bSYour Name  * @psoc: the pointer of wlan_objmgr_psoc
347*5113495bSYour Name  * @data: pointer to data
348*5113495bSYour Name  * @data_len: data length
349*5113495bSYour Name  *
350*5113495bSYour Name  * __wlan_cfg80211_set_gpio_config will forward the GPIO setting to FW by
351*5113495bSYour Name  * WMI_GPIO_CONFIG/OUTPUT_CMDID
352*5113495bSYour Name  *
353*5113495bSYour Name  * Return: 0 on success; errno on failure
354*5113495bSYour Name  */
355*5113495bSYour Name int
wlan_cfg80211_start_gpio_config(struct wiphy * wiphy,struct wlan_objmgr_psoc * psoc,const void * data,int data_len)356*5113495bSYour Name wlan_cfg80211_start_gpio_config(struct wiphy *wiphy,
357*5113495bSYour Name 				struct wlan_objmgr_psoc *psoc,
358*5113495bSYour Name 				const void *data,
359*5113495bSYour Name 				int data_len)
360*5113495bSYour Name {
361*5113495bSYour Name 	uint32_t command;
362*5113495bSYour Name 	struct nlattr *attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MAX + 1];
363*5113495bSYour Name 	int ret;
364*5113495bSYour Name 
365*5113495bSYour Name 	if (wlan_cfg80211_nla_parse(attr, QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MAX,
366*5113495bSYour Name 				    data, data_len,
367*5113495bSYour Name 				    wlan_cfg80211_gpio_config_policy)) {
368*5113495bSYour Name 		return -EINVAL;
369*5113495bSYour Name 	}
370*5113495bSYour Name 
371*5113495bSYour Name 	if (attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND]) {
372*5113495bSYour Name 		command = nla_get_u32(
373*5113495bSYour Name 			attr[QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND]);
374*5113495bSYour Name 
375*5113495bSYour Name 		if (command == QCA_WLAN_VENDOR_GPIO_CONFIG) {
376*5113495bSYour Name 			ret = wlan_set_gpio_config(psoc, attr);
377*5113495bSYour Name 		} else if (command == QCA_WLAN_VENDOR_GPIO_OUTPUT) {
378*5113495bSYour Name 			ret = wlan_set_gpio_output(psoc, attr);
379*5113495bSYour Name 		} else {
380*5113495bSYour Name 			osif_err_rl("Invalid command");
381*5113495bSYour Name 			return -EINVAL;
382*5113495bSYour Name 		}
383*5113495bSYour Name 	} else {
384*5113495bSYour Name 		osif_err_rl("Invalid command");
385*5113495bSYour Name 		return -EINVAL;
386*5113495bSYour Name 	}
387*5113495bSYour Name 
388*5113495bSYour Name 	return ret;
389*5113495bSYour Name }
390*5113495bSYour Name qdf_export_symbol(wlan_cfg80211_start_gpio_config);
391*5113495bSYour Name 
392