1 // SPDX-License-Identifier: GPL-2.0-only
3 // Driver for the regulator based Ethernet Power Sourcing Equipment, without
4 // auto classification support.
6 // Copyright (c) 2022 Pengutronix, Oleksij Rempel <kernel@pengutronix.de>
9 #include <linux/module.h>
11 #include <linux/platform_device.h>
12 #include <linux/pse-pd/pse.h>
13 #include <linux/regulator/consumer.h>
16 struct pse_controller_dev pcdev
;
17 struct regulator
*ps
; /*power source */
18 enum ethtool_podl_pse_admin_state admin_state
;
21 static struct pse_reg_priv
*to_pse_reg(struct pse_controller_dev
*pcdev
)
23 return container_of(pcdev
, struct pse_reg_priv
, pcdev
);
27 pse_reg_pi_enable(struct pse_controller_dev
*pcdev
, int id
)
29 struct pse_reg_priv
*priv
= to_pse_reg(pcdev
);
32 ret
= regulator_enable(priv
->ps
);
36 priv
->admin_state
= ETHTOOL_PODL_PSE_ADMIN_STATE_ENABLED
;
41 pse_reg_pi_disable(struct pse_controller_dev
*pcdev
, int id
)
43 struct pse_reg_priv
*priv
= to_pse_reg(pcdev
);
46 ret
= regulator_disable(priv
->ps
);
50 priv
->admin_state
= ETHTOOL_PODL_PSE_ADMIN_STATE_DISABLED
;
55 pse_reg_pi_is_enabled(struct pse_controller_dev
*pcdev
, int id
)
57 struct pse_reg_priv
*priv
= to_pse_reg(pcdev
);
59 return regulator_is_enabled(priv
->ps
);
63 pse_reg_ethtool_get_status(struct pse_controller_dev
*pcdev
, unsigned long id
,
64 struct netlink_ext_ack
*extack
,
65 struct pse_control_status
*status
)
67 struct pse_reg_priv
*priv
= to_pse_reg(pcdev
);
70 ret
= regulator_is_enabled(priv
->ps
);
75 status
->podl_pw_status
= ETHTOOL_PODL_PSE_PW_D_STATUS_DISABLED
;
77 status
->podl_pw_status
=
78 ETHTOOL_PODL_PSE_PW_D_STATUS_DELIVERING
;
80 status
->podl_admin_state
= priv
->admin_state
;
85 static const struct pse_controller_ops pse_reg_ops
= {
86 .ethtool_get_status
= pse_reg_ethtool_get_status
,
87 .pi_enable
= pse_reg_pi_enable
,
88 .pi_is_enabled
= pse_reg_pi_is_enabled
,
89 .pi_disable
= pse_reg_pi_disable
,
93 pse_reg_probe(struct platform_device
*pdev
)
95 struct device
*dev
= &pdev
->dev
;
96 struct pse_reg_priv
*priv
;
99 priv
= devm_kzalloc(&pdev
->dev
, sizeof(*priv
), GFP_KERNEL
);
103 if (!pdev
->dev
.of_node
)
106 priv
->ps
= devm_regulator_get_exclusive(dev
, "pse");
107 if (IS_ERR(priv
->ps
))
108 return dev_err_probe(dev
, PTR_ERR(priv
->ps
),
109 "failed to get PSE regulator.\n");
111 platform_set_drvdata(pdev
, priv
);
113 ret
= regulator_is_enabled(priv
->ps
);
118 priv
->admin_state
= ETHTOOL_PODL_PSE_ADMIN_STATE_ENABLED
;
120 priv
->admin_state
= ETHTOOL_PODL_PSE_ADMIN_STATE_DISABLED
;
122 priv
->pcdev
.owner
= THIS_MODULE
;
123 priv
->pcdev
.ops
= &pse_reg_ops
;
124 priv
->pcdev
.dev
= dev
;
125 priv
->pcdev
.types
= ETHTOOL_PSE_PODL
;
126 ret
= devm_pse_controller_register(dev
, &priv
->pcdev
);
128 dev_err(dev
, "failed to register PSE controller (%pe)\n",
136 static const __maybe_unused
struct of_device_id pse_reg_of_match
[] = {
137 { .compatible
= "podl-pse-regulator", },
140 MODULE_DEVICE_TABLE(of
, pse_reg_of_match
);
142 static struct platform_driver pse_reg_driver
= {
143 .probe
= pse_reg_probe
,
145 .name
= "PSE regulator",
146 .of_match_table
= of_match_ptr(pse_reg_of_match
),
149 module_platform_driver(pse_reg_driver
);
151 MODULE_AUTHOR("Oleksij Rempel <kernel@pengutronix.de>");
152 MODULE_DESCRIPTION("regulator based Ethernet Power Sourcing Equipment");
153 MODULE_LICENSE("GPL v2");
154 MODULE_ALIAS("platform:pse-regulator");