Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.5.6.
  1// SPDX-License-Identifier: GPL-2.0-only
  2//
  3// Framework for Ethernet Power Sourcing Equipment
  4//
  5// Copyright (c) 2022 Pengutronix, Oleksij Rempel <kernel@pengutronix.de>
  6//
  7
  8#include <linux/device.h>
  9#include <linux/of.h>
 10#include <linux/pse-pd/pse.h>
 11#include <linux/regulator/driver.h>
 12#include <linux/regulator/machine.h>
 13
 14static DEFINE_MUTEX(pse_list_mutex);
 15static LIST_HEAD(pse_controller_list);
 16
 17/**
 18 * struct pse_control - a PSE control
 19 * @pcdev: a pointer to the PSE controller device
 20 *         this PSE control belongs to
 21 * @ps: PSE PI supply of the PSE control
 22 * @list: list entry for the pcdev's PSE controller list
 23 * @id: ID of the PSE line in the PSE controller device
 24 * @refcnt: Number of gets of this pse_control
 25 */
 26struct pse_control {
 27	struct pse_controller_dev *pcdev;
 28	struct regulator *ps;
 29	struct list_head list;
 30	unsigned int id;
 31	struct kref refcnt;
 32};
 33
 34static int of_load_single_pse_pi_pairset(struct device_node *node,
 35					 struct pse_pi *pi,
 36					 int pairset_num)
 37{
 38	struct device_node *pairset_np;
 39	const char *name;
 40	int ret;
 41
 42	ret = of_property_read_string_index(node, "pairset-names",
 43					    pairset_num, &name);
 44	if (ret)
 45		return ret;
 46
 47	if (!strcmp(name, "alternative-a")) {
 48		pi->pairset[pairset_num].pinout = ALTERNATIVE_A;
 49	} else if (!strcmp(name, "alternative-b")) {
 50		pi->pairset[pairset_num].pinout = ALTERNATIVE_B;
 51	} else {
 52		pr_err("pse: wrong pairset-names value %s (%pOF)\n",
 53		       name, node);
 54		return -EINVAL;
 55	}
 56
 57	pairset_np = of_parse_phandle(node, "pairsets", pairset_num);
 58	if (!pairset_np)
 59		return -ENODEV;
 60
 61	pi->pairset[pairset_num].np = pairset_np;
 62
 63	return 0;
 64}
 65
 66/**
 67 * of_load_pse_pi_pairsets - load PSE PI pairsets pinout and polarity
 68 * @node: a pointer of the device node
 69 * @pi: a pointer of the PSE PI to fill
 70 * @npairsets: the number of pairsets (1 or 2) used by the PI
 71 *
 72 * Return: 0 on success and failure value on error
 73 */
 74static int of_load_pse_pi_pairsets(struct device_node *node,
 75				   struct pse_pi *pi,
 76				   int npairsets)
 77{
 78	int i, ret;
 79
 80	ret = of_property_count_strings(node, "pairset-names");
 81	if (ret != npairsets) {
 82		pr_err("pse: amount of pairsets and pairset-names is not equal %d != %d (%pOF)\n",
 83		       npairsets, ret, node);
 84		return -EINVAL;
 85	}
 86
 87	for (i = 0; i < npairsets; i++) {
 88		ret = of_load_single_pse_pi_pairset(node, pi, i);
 89		if (ret)
 90			goto out;
 91	}
 92
 93	if (npairsets == 2 &&
 94	    pi->pairset[0].pinout == pi->pairset[1].pinout) {
 95		pr_err("pse: two PI pairsets can not have identical pinout (%pOF)",
 96		       node);
 97		ret = -EINVAL;
 98	}
 99
100out:
101	/* If an error appears, release all the pairset device node kref */
102	if (ret) {
103		of_node_put(pi->pairset[0].np);
104		pi->pairset[0].np = NULL;
105		of_node_put(pi->pairset[1].np);
106		pi->pairset[1].np = NULL;
107	}
108
109	return ret;
110}
111
112static void pse_release_pis(struct pse_controller_dev *pcdev)
113{
114	int i;
115
116	for (i = 0; i < pcdev->nr_lines; i++) {
117		of_node_put(pcdev->pi[i].pairset[0].np);
118		of_node_put(pcdev->pi[i].pairset[1].np);
119		of_node_put(pcdev->pi[i].np);
120	}
121	kfree(pcdev->pi);
122}
123
124/**
125 * of_load_pse_pis - load all the PSE PIs
126 * @pcdev: a pointer to the PSE controller device
127 *
128 * Return: 0 on success and failure value on error
129 */
130static int of_load_pse_pis(struct pse_controller_dev *pcdev)
131{
132	struct device_node *np = pcdev->dev->of_node;
133	struct device_node *node, *pis;
134	int ret;
135
136	if (!np)
137		return -ENODEV;
138
139	pcdev->pi = kcalloc(pcdev->nr_lines, sizeof(*pcdev->pi), GFP_KERNEL);
140	if (!pcdev->pi)
141		return -ENOMEM;
142
143	pis = of_get_child_by_name(np, "pse-pis");
144	if (!pis) {
145		/* no description of PSE PIs */
146		pcdev->no_of_pse_pi = true;
147		return 0;
148	}
149
150	for_each_child_of_node(pis, node) {
151		struct pse_pi pi = {0};
152		u32 id;
153
154		if (!of_node_name_eq(node, "pse-pi"))
155			continue;
156
157		ret = of_property_read_u32(node, "reg", &id);
158		if (ret) {
159			dev_err(pcdev->dev,
160				"can't get reg property for node '%pOF'",
161				node);
162			goto out;
163		}
164
165		if (id >= pcdev->nr_lines) {
166			dev_err(pcdev->dev,
167				"reg value (%u) is out of range (%u) (%pOF)\n",
168				id, pcdev->nr_lines, node);
169			ret = -EINVAL;
170			goto out;
171		}
172
173		if (pcdev->pi[id].np) {
174			dev_err(pcdev->dev,
175				"other node with same reg value was already registered. %pOF : %pOF\n",
176				pcdev->pi[id].np, node);
177			ret = -EINVAL;
178			goto out;
179		}
180
181		ret = of_count_phandle_with_args(node, "pairsets", NULL);
182		/* npairsets is limited to value one or two */
183		if (ret == 1 || ret == 2) {
184			ret = of_load_pse_pi_pairsets(node, &pi, ret);
185			if (ret)
186				goto out;
187		} else if (ret != ENOENT) {
188			dev_err(pcdev->dev,
189				"error: wrong number of pairsets. Should be 1 or 2, got %d (%pOF)\n",
190				ret, node);
191			ret = -EINVAL;
192			goto out;
193		}
194
195		of_node_get(node);
196		pi.np = node;
197		memcpy(&pcdev->pi[id], &pi, sizeof(pi));
198	}
199
200	of_node_put(pis);
201	return 0;
202
203out:
204	pse_release_pis(pcdev);
205	of_node_put(node);
206	of_node_put(pis);
207	return ret;
208}
209
210static int pse_pi_is_enabled(struct regulator_dev *rdev)
211{
212	struct pse_controller_dev *pcdev = rdev_get_drvdata(rdev);
213	const struct pse_controller_ops *ops;
214	int id, ret;
215
216	ops = pcdev->ops;
217	if (!ops->pi_is_enabled)
218		return -EOPNOTSUPP;
219
220	id = rdev_get_id(rdev);
221	mutex_lock(&pcdev->lock);
222	ret = ops->pi_is_enabled(pcdev, id);
223	mutex_unlock(&pcdev->lock);
224
225	return ret;
226}
227
228static int pse_pi_enable(struct regulator_dev *rdev)
229{
230	struct pse_controller_dev *pcdev = rdev_get_drvdata(rdev);
231	const struct pse_controller_ops *ops;
232	int id, ret;
233
234	ops = pcdev->ops;
235	if (!ops->pi_enable)
236		return -EOPNOTSUPP;
237
238	id = rdev_get_id(rdev);
239	mutex_lock(&pcdev->lock);
240	ret = ops->pi_enable(pcdev, id);
241	if (!ret)
242		pcdev->pi[id].admin_state_enabled = 1;
243	mutex_unlock(&pcdev->lock);
244
245	return ret;
246}
247
248static int pse_pi_disable(struct regulator_dev *rdev)
249{
250	struct pse_controller_dev *pcdev = rdev_get_drvdata(rdev);
251	const struct pse_controller_ops *ops;
252	int id, ret;
253
254	ops = pcdev->ops;
255	if (!ops->pi_disable)
256		return -EOPNOTSUPP;
257
258	id = rdev_get_id(rdev);
259	mutex_lock(&pcdev->lock);
260	ret = ops->pi_disable(pcdev, id);
261	if (!ret)
262		pcdev->pi[id].admin_state_enabled = 0;
263	mutex_unlock(&pcdev->lock);
264
265	return ret;
266}
267
268static int _pse_pi_get_voltage(struct regulator_dev *rdev)
269{
270	struct pse_controller_dev *pcdev = rdev_get_drvdata(rdev);
271	const struct pse_controller_ops *ops;
272	int id;
273
274	ops = pcdev->ops;
275	if (!ops->pi_get_voltage)
276		return -EOPNOTSUPP;
277
278	id = rdev_get_id(rdev);
279	return ops->pi_get_voltage(pcdev, id);
280}
281
282static int pse_pi_get_voltage(struct regulator_dev *rdev)
283{
284	struct pse_controller_dev *pcdev = rdev_get_drvdata(rdev);
285	int ret;
286
287	mutex_lock(&pcdev->lock);
288	ret = _pse_pi_get_voltage(rdev);
289	mutex_unlock(&pcdev->lock);
290
291	return ret;
292}
293
294static int pse_pi_get_current_limit(struct regulator_dev *rdev)
295{
296	struct pse_controller_dev *pcdev = rdev_get_drvdata(rdev);
297	const struct pse_controller_ops *ops;
298	int id, uV, mW, ret;
299	s64 tmp_64;
300
301	ops = pcdev->ops;
302	id = rdev_get_id(rdev);
303	if (!ops->pi_get_pw_limit || !ops->pi_get_voltage)
304		return -EOPNOTSUPP;
305
306	mutex_lock(&pcdev->lock);
307	ret = ops->pi_get_pw_limit(pcdev, id);
308	if (ret < 0)
309		goto out;
310	mW = ret;
311
312	ret = _pse_pi_get_voltage(rdev);
313	if (!ret) {
314		dev_err(pcdev->dev, "Voltage null\n");
315		ret = -ERANGE;
316		goto out;
317	}
318	if (ret < 0)
319		goto out;
320	uV = ret;
321
322	tmp_64 = mW;
323	tmp_64 *= 1000000000ull;
324	/* uA = mW * 1000000000 / uV */
325	ret = DIV_ROUND_CLOSEST_ULL(tmp_64, uV);
326
327out:
328	mutex_unlock(&pcdev->lock);
329	return ret;
330}
331
332static int pse_pi_set_current_limit(struct regulator_dev *rdev, int min_uA,
333				    int max_uA)
334{
335	struct pse_controller_dev *pcdev = rdev_get_drvdata(rdev);
336	const struct pse_controller_ops *ops;
337	int id, mW, ret;
338	s64 tmp_64;
339
340	ops = pcdev->ops;
341	if (!ops->pi_set_pw_limit || !ops->pi_get_voltage)
342		return -EOPNOTSUPP;
343
344	if (max_uA > MAX_PI_CURRENT)
345		return -ERANGE;
346
347	id = rdev_get_id(rdev);
348	mutex_lock(&pcdev->lock);
349	ret = _pse_pi_get_voltage(rdev);
350	if (!ret) {
351		dev_err(pcdev->dev, "Voltage null\n");
352		ret = -ERANGE;
353		goto out;
354	}
355	if (ret < 0)
356		goto out;
357
358	tmp_64 = ret;
359	tmp_64 *= max_uA;
360	/* mW = uA * uV / 1000000000 */
361	mW = DIV_ROUND_CLOSEST_ULL(tmp_64, 1000000000);
362	ret = ops->pi_set_pw_limit(pcdev, id, mW);
363out:
364	mutex_unlock(&pcdev->lock);
365
366	return ret;
367}
368
369static const struct regulator_ops pse_pi_ops = {
370	.is_enabled = pse_pi_is_enabled,
371	.enable = pse_pi_enable,
372	.disable = pse_pi_disable,
373	.get_voltage = pse_pi_get_voltage,
374	.get_current_limit = pse_pi_get_current_limit,
375	.set_current_limit = pse_pi_set_current_limit,
376};
377
378static int
379devm_pse_pi_regulator_register(struct pse_controller_dev *pcdev,
380			       char *name, int id)
381{
382	struct regulator_init_data *rinit_data;
383	struct regulator_config rconfig = {0};
384	struct regulator_desc *rdesc;
385	struct regulator_dev *rdev;
386
387	rinit_data = devm_kzalloc(pcdev->dev, sizeof(*rinit_data),
388				  GFP_KERNEL);
389	if (!rinit_data)
390		return -ENOMEM;
391
392	rdesc = devm_kzalloc(pcdev->dev, sizeof(*rdesc), GFP_KERNEL);
393	if (!rdesc)
394		return -ENOMEM;
395
396	/* Regulator descriptor id have to be the same as its associated
397	 * PSE PI id for the well functioning of the PSE controls.
398	 */
399	rdesc->id = id;
400	rdesc->name = name;
401	rdesc->type = REGULATOR_VOLTAGE;
402	rdesc->ops = &pse_pi_ops;
403	rdesc->owner = pcdev->owner;
404
405	rinit_data->constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS;
406
407	if (pcdev->ops->pi_set_pw_limit)
408		rinit_data->constraints.valid_ops_mask |=
409			REGULATOR_CHANGE_CURRENT;
410
411	rinit_data->supply_regulator = "vpwr";
412
413	rconfig.dev = pcdev->dev;
414	rconfig.driver_data = pcdev;
415	rconfig.init_data = rinit_data;
416
417	rdev = devm_regulator_register(pcdev->dev, rdesc, &rconfig);
418	if (IS_ERR(rdev)) {
419		dev_err_probe(pcdev->dev, PTR_ERR(rdev),
420			      "Failed to register regulator\n");
421		return PTR_ERR(rdev);
422	}
423
424	pcdev->pi[id].rdev = rdev;
425
426	return 0;
427}
428
429/**
430 * pse_controller_register - register a PSE controller device
431 * @pcdev: a pointer to the initialized PSE controller device
432 *
433 * Return: 0 on success and failure value on error
434 */
435int pse_controller_register(struct pse_controller_dev *pcdev)
436{
437	size_t reg_name_len;
438	int ret, i;
439
440	mutex_init(&pcdev->lock);
441	INIT_LIST_HEAD(&pcdev->pse_control_head);
442
443	if (!pcdev->nr_lines)
444		pcdev->nr_lines = 1;
445
446	ret = of_load_pse_pis(pcdev);
447	if (ret)
448		return ret;
449
450	if (pcdev->ops->setup_pi_matrix) {
451		ret = pcdev->ops->setup_pi_matrix(pcdev);
452		if (ret)
453			return ret;
454	}
455
456	/* Each regulator name len is pcdev dev name + 7 char +
457	 * int max digit number (10) + 1
458	 */
459	reg_name_len = strlen(dev_name(pcdev->dev)) + 18;
460
461	/* Register PI regulators */
462	for (i = 0; i < pcdev->nr_lines; i++) {
463		char *reg_name;
464
465		/* Do not register regulator for PIs not described */
466		if (!pcdev->no_of_pse_pi && !pcdev->pi[i].np)
467			continue;
468
469		reg_name = devm_kzalloc(pcdev->dev, reg_name_len, GFP_KERNEL);
470		if (!reg_name)
471			return -ENOMEM;
472
473		snprintf(reg_name, reg_name_len, "pse-%s_pi%d",
474			 dev_name(pcdev->dev), i);
475
476		ret = devm_pse_pi_regulator_register(pcdev, reg_name, i);
477		if (ret)
478			return ret;
479	}
480
481	mutex_lock(&pse_list_mutex);
482	list_add(&pcdev->list, &pse_controller_list);
483	mutex_unlock(&pse_list_mutex);
484
485	return 0;
486}
487EXPORT_SYMBOL_GPL(pse_controller_register);
488
489/**
490 * pse_controller_unregister - unregister a PSE controller device
491 * @pcdev: a pointer to the PSE controller device
492 */
493void pse_controller_unregister(struct pse_controller_dev *pcdev)
494{
495	pse_release_pis(pcdev);
496	mutex_lock(&pse_list_mutex);
497	list_del(&pcdev->list);
498	mutex_unlock(&pse_list_mutex);
499}
500EXPORT_SYMBOL_GPL(pse_controller_unregister);
501
502static void devm_pse_controller_release(struct device *dev, void *res)
503{
504	pse_controller_unregister(*(struct pse_controller_dev **)res);
505}
506
507/**
508 * devm_pse_controller_register - resource managed pse_controller_register()
509 * @dev: device that is registering this PSE controller
510 * @pcdev: a pointer to the initialized PSE controller device
511 *
512 * Managed pse_controller_register(). For PSE controllers registered by
513 * this function, pse_controller_unregister() is automatically called on
514 * driver detach. See pse_controller_register() for more information.
515 *
516 * Return: 0 on success and failure value on error
517 */
518int devm_pse_controller_register(struct device *dev,
519				 struct pse_controller_dev *pcdev)
520{
521	struct pse_controller_dev **pcdevp;
522	int ret;
523
524	pcdevp = devres_alloc(devm_pse_controller_release, sizeof(*pcdevp),
525			      GFP_KERNEL);
526	if (!pcdevp)
527		return -ENOMEM;
528
529	ret = pse_controller_register(pcdev);
530	if (ret) {
531		devres_free(pcdevp);
532		return ret;
533	}
534
535	*pcdevp = pcdev;
536	devres_add(dev, pcdevp);
537
538	return 0;
539}
540EXPORT_SYMBOL_GPL(devm_pse_controller_register);
541
542/* PSE control section */
543
544static void __pse_control_release(struct kref *kref)
545{
546	struct pse_control *psec = container_of(kref, struct pse_control,
547						  refcnt);
548
549	lockdep_assert_held(&pse_list_mutex);
550
551	if (psec->pcdev->pi[psec->id].admin_state_enabled)
552		regulator_disable(psec->ps);
553	devm_regulator_put(psec->ps);
554
555	module_put(psec->pcdev->owner);
556
557	list_del(&psec->list);
558	kfree(psec);
559}
560
561static void __pse_control_put_internal(struct pse_control *psec)
562{
563	lockdep_assert_held(&pse_list_mutex);
564
565	kref_put(&psec->refcnt, __pse_control_release);
566}
567
568/**
569 * pse_control_put - free the PSE control
570 * @psec: PSE control pointer
571 */
572void pse_control_put(struct pse_control *psec)
573{
574	if (IS_ERR_OR_NULL(psec))
575		return;
576
577	mutex_lock(&pse_list_mutex);
578	__pse_control_put_internal(psec);
579	mutex_unlock(&pse_list_mutex);
580}
581EXPORT_SYMBOL_GPL(pse_control_put);
582
583static struct pse_control *
584pse_control_get_internal(struct pse_controller_dev *pcdev, unsigned int index)
585{
586	struct pse_control *psec;
587	int ret;
588
589	lockdep_assert_held(&pse_list_mutex);
590
591	list_for_each_entry(psec, &pcdev->pse_control_head, list) {
592		if (psec->id == index) {
593			kref_get(&psec->refcnt);
594			return psec;
595		}
596	}
597
598	psec = kzalloc(sizeof(*psec), GFP_KERNEL);
599	if (!psec)
600		return ERR_PTR(-ENOMEM);
601
602	if (!try_module_get(pcdev->owner)) {
603		ret = -ENODEV;
604		goto free_psec;
605	}
606
607	psec->ps = devm_regulator_get_exclusive(pcdev->dev,
608						rdev_get_name(pcdev->pi[index].rdev));
609	if (IS_ERR(psec->ps)) {
610		ret = PTR_ERR(psec->ps);
611		goto put_module;
612	}
613
614	ret = regulator_is_enabled(psec->ps);
615	if (ret < 0)
616		goto regulator_put;
617
618	pcdev->pi[index].admin_state_enabled = ret;
619
620	psec->pcdev = pcdev;
621	list_add(&psec->list, &pcdev->pse_control_head);
622	psec->id = index;
623	kref_init(&psec->refcnt);
624
625	return psec;
626
627regulator_put:
628	devm_regulator_put(psec->ps);
629put_module:
630	module_put(pcdev->owner);
631free_psec:
632	kfree(psec);
633
634	return ERR_PTR(ret);
635}
636
637/**
638 * of_pse_match_pi - Find the PSE PI id matching the device node phandle
639 * @pcdev: a pointer to the PSE controller device
640 * @np: a pointer to the device node
641 *
642 * Return: id of the PSE PI, -EINVAL if not found
643 */
644static int of_pse_match_pi(struct pse_controller_dev *pcdev,
645			   struct device_node *np)
646{
647	int i;
648
649	for (i = 0; i < pcdev->nr_lines; i++) {
650		if (pcdev->pi[i].np == np)
651			return i;
652	}
653
654	return -EINVAL;
655}
656
657/**
658 * psec_id_xlate - translate pse_spec to the PSE line number according
659 *		   to the number of pse-cells in case of no pse_pi node
660 * @pcdev: a pointer to the PSE controller device
661 * @pse_spec: PSE line specifier as found in the device tree
662 *
663 * Return: 0 if #pse-cells = <0>. Return PSE line number otherwise.
664 */
665static int psec_id_xlate(struct pse_controller_dev *pcdev,
666			 const struct of_phandle_args *pse_spec)
667{
668	if (!pcdev->of_pse_n_cells)
669		return 0;
670
671	if (pcdev->of_pse_n_cells > 1 ||
672	    pse_spec->args[0] >= pcdev->nr_lines)
673		return -EINVAL;
674
675	return pse_spec->args[0];
676}
677
678struct pse_control *of_pse_control_get(struct device_node *node)
679{
680	struct pse_controller_dev *r, *pcdev;
681	struct of_phandle_args args;
682	struct pse_control *psec;
683	int psec_id;
684	int ret;
685
686	if (!node)
687		return ERR_PTR(-EINVAL);
688
689	ret = of_parse_phandle_with_args(node, "pses", "#pse-cells", 0, &args);
690	if (ret)
691		return ERR_PTR(ret);
692
693	mutex_lock(&pse_list_mutex);
694	pcdev = NULL;
695	list_for_each_entry(r, &pse_controller_list, list) {
696		if (!r->no_of_pse_pi) {
697			ret = of_pse_match_pi(r, args.np);
698			if (ret >= 0) {
699				pcdev = r;
700				psec_id = ret;
701				break;
702			}
703		} else if (args.np == r->dev->of_node) {
704			pcdev = r;
705			break;
706		}
707	}
708
709	if (!pcdev) {
710		psec = ERR_PTR(-EPROBE_DEFER);
711		goto out;
712	}
713
714	if (WARN_ON(args.args_count != pcdev->of_pse_n_cells)) {
715		psec = ERR_PTR(-EINVAL);
716		goto out;
717	}
718
719	if (pcdev->no_of_pse_pi) {
720		psec_id = psec_id_xlate(pcdev, &args);
721		if (psec_id < 0) {
722			psec = ERR_PTR(psec_id);
723			goto out;
724		}
725	}
726
727	/* pse_list_mutex also protects the pcdev's pse_control list */
728	psec = pse_control_get_internal(pcdev, psec_id);
729
730out:
731	mutex_unlock(&pse_list_mutex);
732	of_node_put(args.np);
733
734	return psec;
735}
736EXPORT_SYMBOL_GPL(of_pse_control_get);
737
738/**
739 * pse_ethtool_get_status - get status of PSE control
740 * @psec: PSE control pointer
741 * @extack: extack for reporting useful error messages
742 * @status: struct to store PSE status
743 *
744 * Return: 0 on success and failure value on error
745 */
746int pse_ethtool_get_status(struct pse_control *psec,
747			   struct netlink_ext_ack *extack,
748			   struct pse_control_status *status)
749{
750	const struct pse_controller_ops *ops;
751	struct pse_controller_dev *pcdev;
752	int err;
753
754	pcdev = psec->pcdev;
755	ops = pcdev->ops;
756	if (!ops->ethtool_get_status) {
757		NL_SET_ERR_MSG(extack,
758			       "PSE driver does not support status report");
759		return -EOPNOTSUPP;
760	}
761
762	mutex_lock(&pcdev->lock);
763	err = ops->ethtool_get_status(pcdev, psec->id, extack, status);
764	mutex_unlock(&pcdev->lock);
765
766	return err;
767}
768EXPORT_SYMBOL_GPL(pse_ethtool_get_status);
769
770static int pse_ethtool_c33_set_config(struct pse_control *psec,
771				      const struct pse_control_config *config)
772{
773	int err = 0;
774
775	/* Look at admin_state_enabled status to not call regulator_enable
776	 * or regulator_disable twice creating a regulator counter mismatch
777	 */
778	switch (config->c33_admin_control) {
779	case ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED:
780		/* We could have mismatch between admin_state_enabled and
781		 * state reported by regulator_is_enabled. This can occur when
782		 * the PI is forcibly turn off by the controller. Call
783		 * regulator_disable on that case to fix the counters state.
784		 */
785		if (psec->pcdev->pi[psec->id].admin_state_enabled &&
786		    !regulator_is_enabled(psec->ps)) {
787			err = regulator_disable(psec->ps);
788			if (err)
789				break;
790		}
791		if (!psec->pcdev->pi[psec->id].admin_state_enabled)
792			err = regulator_enable(psec->ps);
793		break;
794	case ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED:
795		if (psec->pcdev->pi[psec->id].admin_state_enabled)
796			err = regulator_disable(psec->ps);
797		break;
798	default:
799		err = -EOPNOTSUPP;
800	}
801
802	return err;
803}
804
805static int pse_ethtool_podl_set_config(struct pse_control *psec,
806				       const struct pse_control_config *config)
807{
808	int err = 0;
809
810	/* Look at admin_state_enabled status to not call regulator_enable
811	 * or regulator_disable twice creating a regulator counter mismatch
812	 */
813	switch (config->podl_admin_control) {
814	case ETHTOOL_PODL_PSE_ADMIN_STATE_ENABLED:
815		if (!psec->pcdev->pi[psec->id].admin_state_enabled)
816			err = regulator_enable(psec->ps);
817		break;
818	case ETHTOOL_PODL_PSE_ADMIN_STATE_DISABLED:
819		if (psec->pcdev->pi[psec->id].admin_state_enabled)
820			err = regulator_disable(psec->ps);
821		break;
822	default:
823		err = -EOPNOTSUPP;
824	}
825
826	return err;
827}
828
829/**
830 * pse_ethtool_set_config - set PSE control configuration
831 * @psec: PSE control pointer
832 * @extack: extack for reporting useful error messages
833 * @config: Configuration of the test to run
834 *
835 * Return: 0 on success and failure value on error
836 */
837int pse_ethtool_set_config(struct pse_control *psec,
838			   struct netlink_ext_ack *extack,
839			   const struct pse_control_config *config)
840{
841	int err = 0;
842
843	if (pse_has_c33(psec) && config->c33_admin_control) {
844		err = pse_ethtool_c33_set_config(psec, config);
845		if (err)
846			return err;
847	}
848
849	if (pse_has_podl(psec) && config->podl_admin_control)
850		err = pse_ethtool_podl_set_config(psec, config);
851
852	return err;
853}
854EXPORT_SYMBOL_GPL(pse_ethtool_set_config);
855
856/**
857 * pse_ethtool_set_pw_limit - set PSE control power limit
858 * @psec: PSE control pointer
859 * @extack: extack for reporting useful error messages
860 * @pw_limit: power limit value in mW
861 *
862 * Return: 0 on success and failure value on error
863 */
864int pse_ethtool_set_pw_limit(struct pse_control *psec,
865			     struct netlink_ext_ack *extack,
866			     const unsigned int pw_limit)
867{
868	int uV, uA, ret;
869	s64 tmp_64;
870
871	ret = regulator_get_voltage(psec->ps);
872	if (!ret) {
873		NL_SET_ERR_MSG(extack,
874			       "Can't calculate the current, PSE voltage read is 0");
875		return -ERANGE;
876	}
877	if (ret < 0) {
878		NL_SET_ERR_MSG(extack,
879			       "Error reading PSE voltage");
880		return ret;
881	}
882	uV = ret;
883
884	tmp_64 = pw_limit;
885	tmp_64 *= 1000000000ull;
886	/* uA = mW * 1000000000 / uV */
887	uA = DIV_ROUND_CLOSEST_ULL(tmp_64, uV);
888
889	return regulator_set_current_limit(psec->ps, 0, uA);
890}
891EXPORT_SYMBOL_GPL(pse_ethtool_set_pw_limit);
892
893bool pse_has_podl(struct pse_control *psec)
894{
895	return psec->pcdev->types & ETHTOOL_PSE_PODL;
896}
897EXPORT_SYMBOL_GPL(pse_has_podl);
898
899bool pse_has_c33(struct pse_control *psec)
900{
901	return psec->pcdev->types & ETHTOOL_PSE_C33;
902}
903EXPORT_SYMBOL_GPL(pse_has_c33);