File Index
Files and directories
Sign in
FILE

pinctrl-scmi.c

File preview with syntax highlighting.

linux-6.19.14/drivers/pinctrl/pinctrl-scmi.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * System Control and Power Interface (SCMI) Protocol based pinctrl driver
  4 *
  5 * Copyright (C) 2024 EPAM
  6 * Copyright 2024 NXP
  7 */
  8
  9#include <linux/device.h>
 10#include <linux/err.h>
 11#include <linux/errno.h>
 12#include <linux/module.h>
 13#include <linux/mod_devicetable.h>
 14#include <linux/of.h>
 15#include <linux/scmi_protocol.h>
 16#include <linux/slab.h>
 17#include <linux/types.h>
 18
 19#include <linux/pinctrl/machine.h>
 20#include <linux/pinctrl/pinconf.h>
 21#include <linux/pinctrl/pinconf-generic.h>
 22#include <linux/pinctrl/pinctrl.h>
 23#include <linux/pinctrl/pinmux.h>
 24
 25#include "pinctrl-utils.h"
 26#include "core.h"
 27#include "pinconf.h"
 28
 29#define DRV_NAME "scmi-pinctrl"
 30
 31/* Define num configs, if not large than 4 use stack, else use kcalloc() */
 32#define SCMI_NUM_CONFIGS	4
 33
 34static const struct scmi_pinctrl_proto_ops *pinctrl_ops;
 35
 36struct scmi_pinctrl {
 37	struct device *dev;
 38	struct scmi_protocol_handle *ph;
 39	struct pinctrl_dev *pctldev;
 40	struct pinctrl_desc pctl_desc;
 41	struct pinfunction *functions;
 42	unsigned int nr_functions;
 43};
 44
 45static int pinctrl_scmi_get_groups_count(struct pinctrl_dev *pctldev)
 46{
 47	struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
 48
 49	return pinctrl_ops->count_get(pmx->ph, GROUP_TYPE);
 50}
 51
 52static const char *pinctrl_scmi_get_group_name(struct pinctrl_dev *pctldev,
 53					       unsigned int selector)
 54{
 55	int ret;
 56	const char *name;
 57	struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
 58
 59	ret = pinctrl_ops->name_get(pmx->ph, selector, GROUP_TYPE, &name);
 60	if (ret) {
 61		dev_err(pmx->dev, "get name failed with err %d", ret);
 62		return NULL;
 63	}
 64
 65	return name;
 66}
 67
 68static int pinctrl_scmi_get_group_pins(struct pinctrl_dev *pctldev,
 69				       unsigned int selector,
 70				       const unsigned int **pins,
 71				       unsigned int *num_pins)
 72{
 73	struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
 74
 75	return pinctrl_ops->group_pins_get(pmx->ph, selector, pins, num_pins);
 76}
 77
 78static const struct pinctrl_ops pinctrl_scmi_pinctrl_ops = {
 79	.get_groups_count = pinctrl_scmi_get_groups_count,
 80	.get_group_name = pinctrl_scmi_get_group_name,
 81	.get_group_pins = pinctrl_scmi_get_group_pins,
 82#ifdef CONFIG_OF
 83	.dt_node_to_map = pinconf_generic_dt_node_to_map_all,
 84	.dt_free_map = pinconf_generic_dt_free_map,
 85#endif
 86};
 87
 88static int pinctrl_scmi_get_functions_count(struct pinctrl_dev *pctldev)
 89{
 90	struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
 91
 92	return pinctrl_ops->count_get(pmx->ph, FUNCTION_TYPE);
 93}
 94
 95static const char *pinctrl_scmi_get_function_name(struct pinctrl_dev *pctldev,
 96						  unsigned int selector)
 97{
 98	int ret;
 99	const char *name;
100	struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
101
102	ret = pinctrl_ops->name_get(pmx->ph, selector, FUNCTION_TYPE, &name);
103	if (ret) {
104		dev_err(pmx->dev, "get name failed with err %d", ret);
105		return NULL;
106	}
107
108	return name;
109}
110
111static int pinctrl_scmi_get_function_groups(struct pinctrl_dev *pctldev,
112					    unsigned int selector,
113					    const char * const **p_groups,
114					    unsigned int * const p_num_groups)
115{
116	struct pinfunction *func;
117	const unsigned int *group_ids;
118	unsigned int num_groups;
119	const char **groups;
120	int ret, i;
121	struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
122
123	if (!p_groups || !p_num_groups)
124		return -EINVAL;
125
126	if (selector >= pmx->nr_functions)
127		return -EINVAL;
128
129	func = &pmx->functions[selector];
130	if (func->ngroups)
131		goto done;
132
133	ret = pinctrl_ops->function_groups_get(pmx->ph, selector, &num_groups,
134					       &group_ids);
135	if (ret) {
136		dev_err(pmx->dev, "Unable to get function groups, err %d", ret);
137		return ret;
138	}
139	if (!num_groups)
140		return -EINVAL;
141
142	groups = kcalloc(num_groups, sizeof(*groups), GFP_KERNEL);
143	if (!groups)
144		return -ENOMEM;
145
146	for (i = 0; i < num_groups; i++) {
147		groups[i] = pinctrl_scmi_get_group_name(pctldev, group_ids[i]);
148		if (!groups[i]) {
149			ret = -EINVAL;
150			goto err_free;
151		}
152	}
153
154	func->ngroups = num_groups;
155	func->groups = groups;
156done:
157	*p_groups = func->groups;
158	*p_num_groups = func->ngroups;
159
160	return 0;
161
162err_free:
163	kfree(groups);
164
165	return ret;
166}
167
168static int pinctrl_scmi_func_set_mux(struct pinctrl_dev *pctldev,
169				     unsigned int selector, unsigned int group)
170{
171	struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
172
173	return pinctrl_ops->mux_set(pmx->ph, selector, group);
174}
175
176static int pinctrl_scmi_request(struct pinctrl_dev *pctldev,
177				unsigned int offset)
178{
179	struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
180
181	return pinctrl_ops->pin_request(pmx->ph, offset);
182}
183
184static int pinctrl_scmi_free(struct pinctrl_dev *pctldev, unsigned int offset)
185{
186	struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
187
188	return pinctrl_ops->pin_free(pmx->ph, offset);
189}
190
191static const struct pinmux_ops pinctrl_scmi_pinmux_ops = {
192	.request = pinctrl_scmi_request,
193	.free = pinctrl_scmi_free,
194	.get_functions_count = pinctrl_scmi_get_functions_count,
195	.get_function_name = pinctrl_scmi_get_function_name,
196	.get_function_groups = pinctrl_scmi_get_function_groups,
197	.set_mux = pinctrl_scmi_func_set_mux,
198};
199
200static int pinctrl_scmi_map_pinconf_type(enum pin_config_param param,
201					 enum scmi_pinctrl_conf_type *type)
202{
203	u32 arg = param;
204
205	switch (arg) {
206	case PIN_CONFIG_BIAS_BUS_HOLD:
207		*type = SCMI_PIN_BIAS_BUS_HOLD;
208		break;
209	case PIN_CONFIG_BIAS_DISABLE:
210		*type = SCMI_PIN_BIAS_DISABLE;
211		break;
212	case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
213		*type = SCMI_PIN_BIAS_HIGH_IMPEDANCE;
214		break;
215	case PIN_CONFIG_BIAS_PULL_DOWN:
216		*type = SCMI_PIN_BIAS_PULL_DOWN;
217		break;
218	case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
219		*type = SCMI_PIN_BIAS_PULL_DEFAULT;
220		break;
221	case PIN_CONFIG_BIAS_PULL_UP:
222		*type = SCMI_PIN_BIAS_PULL_UP;
223		break;
224	case PIN_CONFIG_DRIVE_OPEN_DRAIN:
225		*type = SCMI_PIN_DRIVE_OPEN_DRAIN;
226		break;
227	case PIN_CONFIG_DRIVE_OPEN_SOURCE:
228		*type = SCMI_PIN_DRIVE_OPEN_SOURCE;
229		break;
230	case PIN_CONFIG_DRIVE_PUSH_PULL:
231		*type = SCMI_PIN_DRIVE_PUSH_PULL;
232		break;
233	case PIN_CONFIG_DRIVE_STRENGTH:
234		*type = SCMI_PIN_DRIVE_STRENGTH;
235		break;
236	case PIN_CONFIG_DRIVE_STRENGTH_UA:
237		*type = SCMI_PIN_DRIVE_STRENGTH;
238		break;
239	case PIN_CONFIG_INPUT_DEBOUNCE:
240		*type = SCMI_PIN_INPUT_DEBOUNCE;
241		break;
242	case PIN_CONFIG_INPUT_ENABLE:
243		*type = SCMI_PIN_INPUT_MODE;
244		break;
245	case PIN_CONFIG_INPUT_SCHMITT:
246		*type = SCMI_PIN_INPUT_SCHMITT;
247		break;
248	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
249		*type = SCMI_PIN_INPUT_MODE;
250		break;
251	case PIN_CONFIG_MODE_LOW_POWER:
252		*type = SCMI_PIN_LOW_POWER_MODE;
253		break;
254	case PIN_CONFIG_LEVEL:
255		*type = SCMI_PIN_OUTPUT_VALUE;
256		break;
257	case PIN_CONFIG_OUTPUT_ENABLE:
258		*type = SCMI_PIN_OUTPUT_MODE;
259		break;
260	case PIN_CONFIG_OUTPUT_IMPEDANCE_OHMS:
261		*type = SCMI_PIN_OUTPUT_VALUE;
262		break;
263	case PIN_CONFIG_POWER_SOURCE:
264		*type = SCMI_PIN_POWER_SOURCE;
265		break;
266	case PIN_CONFIG_SLEW_RATE:
267		*type = SCMI_PIN_SLEW_RATE;
268		break;
269	case SCMI_PIN_OEM_START ... SCMI_PIN_OEM_END:
270		*type = arg;
271		break;
272	default:
273		return -EINVAL;
274	}
275
276	return 0;
277}
278
279static int pinctrl_scmi_pinconf_get(struct pinctrl_dev *pctldev,
280				    unsigned int pin, unsigned long *config)
281{
282	int ret;
283	struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
284	enum pin_config_param config_type;
285	enum scmi_pinctrl_conf_type type;
286	u32 config_value;
287
288	if (!config)
289		return -EINVAL;
290
291	config_type = pinconf_to_config_param(*config);
292
293	ret = pinctrl_scmi_map_pinconf_type(config_type, &type);
294	if (ret)
295		return ret;
296
297	ret = pinctrl_ops->settings_get_one(pmx->ph, pin, PIN_TYPE, type,
298					    &config_value);
299	/* Convert SCMI error code to PINCTRL expected error code */
300	if (ret == -EOPNOTSUPP)
301		return -ENOTSUPP;
302	if (ret)
303		return ret;
304
305	*config = pinconf_to_config_packed(config_type, config_value);
306
307	return 0;
308}
309
310static int
311pinctrl_scmi_alloc_configs(struct pinctrl_dev *pctldev, u32 num_configs,
312			   u32 **p_config_value,
313			   enum scmi_pinctrl_conf_type **p_config_type)
314{
315	if (num_configs <= SCMI_NUM_CONFIGS)
316		return 0;
317
318	*p_config_value = kcalloc(num_configs, sizeof(**p_config_value), GFP_KERNEL);
319	if (!*p_config_value)
320		return -ENOMEM;
321
322	*p_config_type = kcalloc(num_configs, sizeof(**p_config_type), GFP_KERNEL);
323	if (!*p_config_type) {
324		kfree(*p_config_value);
325		return -ENOMEM;
326	}
327
328	return 0;
329}
330
331static void
332pinctrl_scmi_free_configs(struct pinctrl_dev *pctldev, u32 num_configs,
333			  u32 **p_config_value,
334			  enum scmi_pinctrl_conf_type **p_config_type)
335{
336	if (num_configs <= SCMI_NUM_CONFIGS)
337		return;
338
339	kfree(*p_config_value);
340	kfree(*p_config_type);
341}
342
343static int pinctrl_scmi_pinconf_set(struct pinctrl_dev *pctldev,
344				    unsigned int pin,
345				    unsigned long *configs,
346				    unsigned int num_configs)
347{
348	int i, ret;
349	struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
350	enum scmi_pinctrl_conf_type config_type[SCMI_NUM_CONFIGS];
351	u32 config_value[SCMI_NUM_CONFIGS];
352	enum scmi_pinctrl_conf_type *p_config_type = config_type;
353	u32 *p_config_value = config_value;
354	enum pin_config_param param;
355
356	if (!configs || !num_configs)
357		return -EINVAL;
358
359	ret = pinctrl_scmi_alloc_configs(pctldev, num_configs, &p_config_type,
360					 &p_config_value);
361	if (ret)
362		return ret;
363
364	for (i = 0; i < num_configs; i++) {
365		param = pinconf_to_config_param(configs[i]);
366		ret = pinctrl_scmi_map_pinconf_type(param, &p_config_type[i]);
367		if (ret) {
368			dev_err(pmx->dev, "Error map pinconf_type %d\n", ret);
369			goto free_config;
370		}
371		p_config_value[i] = pinconf_to_config_argument(configs[i]);
372	}
373
374	ret = pinctrl_ops->settings_conf(pmx->ph, pin, PIN_TYPE, num_configs,
375					 p_config_type,  p_config_value);
376	if (ret)
377		dev_err(pmx->dev, "Error parsing config %d\n", ret);
378
379free_config:
380	pinctrl_scmi_free_configs(pctldev, num_configs, &p_config_type,
381				  &p_config_value);
382	return ret;
383}
384
385static int pinctrl_scmi_pinconf_group_set(struct pinctrl_dev *pctldev,
386					  unsigned int group,
387					  unsigned long *configs,
388					  unsigned int num_configs)
389{
390	int i, ret;
391	struct scmi_pinctrl *pmx =  pinctrl_dev_get_drvdata(pctldev);
392	enum scmi_pinctrl_conf_type config_type[SCMI_NUM_CONFIGS];
393	u32 config_value[SCMI_NUM_CONFIGS];
394	enum scmi_pinctrl_conf_type *p_config_type = config_type;
395	u32 *p_config_value = config_value;
396	enum pin_config_param param;
397
398	if (!configs || !num_configs)
399		return -EINVAL;
400
401	ret = pinctrl_scmi_alloc_configs(pctldev, num_configs, &p_config_type,
402					 &p_config_value);
403	if (ret)
404		return ret;
405
406	for (i = 0; i < num_configs; i++) {
407		param = pinconf_to_config_param(configs[i]);
408		ret = pinctrl_scmi_map_pinconf_type(param, &p_config_type[i]);
409		if (ret) {
410			dev_err(pmx->dev, "Error map pinconf_type %d\n", ret);
411			goto free_config;
412		}
413
414		p_config_value[i] = pinconf_to_config_argument(configs[i]);
415	}
416
417	ret = pinctrl_ops->settings_conf(pmx->ph, group, GROUP_TYPE,
418					 num_configs, p_config_type,
419					 p_config_value);
420	if (ret)
421		dev_err(pmx->dev, "Error parsing config %d", ret);
422
423free_config:
424	pinctrl_scmi_free_configs(pctldev, num_configs, &p_config_type,
425				  &p_config_value);
426	return ret;
427};
428
429static int pinctrl_scmi_pinconf_group_get(struct pinctrl_dev *pctldev,
430					  unsigned int group,
431					  unsigned long *config)
432{
433	int ret;
434	struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
435	enum pin_config_param config_type;
436	enum scmi_pinctrl_conf_type type;
437	u32 config_value;
438
439	if (!config)
440		return -EINVAL;
441
442	config_type = pinconf_to_config_param(*config);
443	ret = pinctrl_scmi_map_pinconf_type(config_type, &type);
444	if (ret) {
445		dev_err(pmx->dev, "Error map pinconf_type %d\n", ret);
446		return ret;
447	}
448
449	ret = pinctrl_ops->settings_get_one(pmx->ph, group, GROUP_TYPE, type,
450					    &config_value);
451	/* Convert SCMI error code to PINCTRL expected error code */
452	if (ret == -EOPNOTSUPP)
453		return -ENOTSUPP;
454	if (ret)
455		return ret;
456
457	*config = pinconf_to_config_packed(config_type, config_value);
458
459	return 0;
460}
461
462static const struct pinconf_ops pinctrl_scmi_pinconf_ops = {
463	.is_generic = true,
464	.pin_config_get = pinctrl_scmi_pinconf_get,
465	.pin_config_set = pinctrl_scmi_pinconf_set,
466	.pin_config_group_set = pinctrl_scmi_pinconf_group_set,
467	.pin_config_group_get = pinctrl_scmi_pinconf_group_get,
468	.pin_config_config_dbg_show = pinconf_generic_dump_config,
469};
470
471static int pinctrl_scmi_get_pins(struct scmi_pinctrl *pmx,
472				 struct pinctrl_desc *desc)
473{
474	struct pinctrl_pin_desc *pins;
475	unsigned int npins;
476	int ret, i;
477
478	npins = pinctrl_ops->count_get(pmx->ph, PIN_TYPE);
479	/*
480	 * npins will never be zero, the scmi pinctrl driver has bailed out
481	 * if npins is zero.
482	 */
483	pins = devm_kmalloc_array(pmx->dev, npins, sizeof(*pins), GFP_KERNEL);
484	if (!pins)
485		return -ENOMEM;
486
487	for (i = 0; i < npins; i++) {
488		pins[i].number = i;
489		/*
490		 * The memory for name is handled by the scmi firmware driver,
491		 * no need free here
492		 */
493		ret = pinctrl_ops->name_get(pmx->ph, i, PIN_TYPE, &pins[i].name);
494		if (ret)
495			return dev_err_probe(pmx->dev, ret,
496					     "Can't get name for pin %d", i);
497	}
498
499	desc->npins = npins;
500	desc->pins = pins;
501	dev_dbg(pmx->dev, "got pins %u", npins);
502
503	return 0;
504}
505
506static const char * const scmi_pinctrl_blocklist[] = {
507	"fsl,imx95",
508	"fsl,imx94",
509	NULL
510};
511
512static int scmi_pinctrl_probe(struct scmi_device *sdev)
513{
514	int ret;
515	struct device *dev = &sdev->dev;
516	struct scmi_pinctrl *pmx;
517	const struct scmi_handle *handle;
518	struct scmi_protocol_handle *ph;
519
520	if (!sdev->handle)
521		return -EINVAL;
522
523	if (of_machine_compatible_match(scmi_pinctrl_blocklist))
524		return -ENODEV;
525
526	handle = sdev->handle;
527
528	pinctrl_ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_PINCTRL, &ph);
529	if (IS_ERR(pinctrl_ops))
530		return PTR_ERR(pinctrl_ops);
531
532	pmx = devm_kzalloc(dev, sizeof(*pmx), GFP_KERNEL);
533	if (!pmx)
534		return -ENOMEM;
535
536	pmx->ph = ph;
537
538	pmx->dev = dev;
539	pmx->pctl_desc.name = DRV_NAME;
540	pmx->pctl_desc.owner = THIS_MODULE;
541	pmx->pctl_desc.pctlops = &pinctrl_scmi_pinctrl_ops;
542	pmx->pctl_desc.pmxops = &pinctrl_scmi_pinmux_ops;
543	pmx->pctl_desc.confops = &pinctrl_scmi_pinconf_ops;
544
545	ret = pinctrl_scmi_get_pins(pmx, &pmx->pctl_desc);
546	if (ret)
547		return ret;
548
549	ret = devm_pinctrl_register_and_init(dev, &pmx->pctl_desc, pmx,
550					     &pmx->pctldev);
551	if (ret)
552		return dev_err_probe(dev, ret, "Failed to register pinctrl\n");
553
554	pmx->nr_functions = pinctrl_scmi_get_functions_count(pmx->pctldev);
555	pmx->functions = devm_kcalloc(dev, pmx->nr_functions,
556				      sizeof(*pmx->functions), GFP_KERNEL);
557	if (!pmx->functions)
558		return -ENOMEM;
559
560	return pinctrl_enable(pmx->pctldev);
561}
562
563static const struct scmi_device_id scmi_id_table[] = {
564	{ SCMI_PROTOCOL_PINCTRL, "pinctrl" },
565	{ }
566};
567MODULE_DEVICE_TABLE(scmi, scmi_id_table);
568
569static struct scmi_driver scmi_pinctrl_driver = {
570	.name = DRV_NAME,
571	.probe = scmi_pinctrl_probe,
572	.id_table = scmi_id_table,
573};
574module_scmi_driver(scmi_pinctrl_driver);
575
576MODULE_AUTHOR("Oleksii Moisieiev <oleksii_moisieiev@epam.com>");
577MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>");
578MODULE_DESCRIPTION("ARM SCMI pin controller driver");
579MODULE_LICENSE("GPL");
~/ Read-only file preview.