xref: /linux/drivers/phy/phy-nxp-ptn3222.c (revision 25768de50b1f2dbb6ea44bd5148a87fe2c9c3688)
1*c9be539eSDmitry Baryshkov // SPDX-License-Identifier: GPL-2.0
2*c9be539eSDmitry Baryshkov /*
3*c9be539eSDmitry Baryshkov  * Copyright (c) 2024, Linaro Limited
4*c9be539eSDmitry Baryshkov  */
5*c9be539eSDmitry Baryshkov 
6*c9be539eSDmitry Baryshkov #include <linux/gpio/consumer.h>
7*c9be539eSDmitry Baryshkov #include <linux/i2c.h>
8*c9be539eSDmitry Baryshkov #include <linux/module.h>
9*c9be539eSDmitry Baryshkov #include <linux/of.h>
10*c9be539eSDmitry Baryshkov #include <linux/phy/phy.h>
11*c9be539eSDmitry Baryshkov #include <linux/regmap.h>
12*c9be539eSDmitry Baryshkov #include <linux/regulator/consumer.h>
13*c9be539eSDmitry Baryshkov 
14*c9be539eSDmitry Baryshkov #define NUM_SUPPLIES 2
15*c9be539eSDmitry Baryshkov 
16*c9be539eSDmitry Baryshkov struct ptn3222 {
17*c9be539eSDmitry Baryshkov 	struct i2c_client *client;
18*c9be539eSDmitry Baryshkov 	struct phy *phy;
19*c9be539eSDmitry Baryshkov 	struct gpio_desc *reset_gpio;
20*c9be539eSDmitry Baryshkov 	struct regulator_bulk_data *supplies;
21*c9be539eSDmitry Baryshkov };
22*c9be539eSDmitry Baryshkov 
23*c9be539eSDmitry Baryshkov static int ptn3222_init(struct phy *phy)
24*c9be539eSDmitry Baryshkov {
25*c9be539eSDmitry Baryshkov 	struct ptn3222 *ptn3222 = phy_get_drvdata(phy);
26*c9be539eSDmitry Baryshkov 	int ret;
27*c9be539eSDmitry Baryshkov 
28*c9be539eSDmitry Baryshkov 	ret = regulator_bulk_enable(NUM_SUPPLIES, ptn3222->supplies);
29*c9be539eSDmitry Baryshkov 	if (ret)
30*c9be539eSDmitry Baryshkov 		return ret;
31*c9be539eSDmitry Baryshkov 
32*c9be539eSDmitry Baryshkov 	gpiod_set_value_cansleep(ptn3222->reset_gpio, 0);
33*c9be539eSDmitry Baryshkov 
34*c9be539eSDmitry Baryshkov 	return 0;
35*c9be539eSDmitry Baryshkov }
36*c9be539eSDmitry Baryshkov 
37*c9be539eSDmitry Baryshkov static int ptn3222_exit(struct phy *phy)
38*c9be539eSDmitry Baryshkov {
39*c9be539eSDmitry Baryshkov 	struct ptn3222 *ptn3222 = phy_get_drvdata(phy);
40*c9be539eSDmitry Baryshkov 
41*c9be539eSDmitry Baryshkov 	gpiod_set_value_cansleep(ptn3222->reset_gpio, 1);
42*c9be539eSDmitry Baryshkov 
43*c9be539eSDmitry Baryshkov 	return regulator_bulk_disable(NUM_SUPPLIES, ptn3222->supplies);
44*c9be539eSDmitry Baryshkov }
45*c9be539eSDmitry Baryshkov 
46*c9be539eSDmitry Baryshkov static const struct phy_ops ptn3222_ops = {
47*c9be539eSDmitry Baryshkov 	.init		= ptn3222_init,
48*c9be539eSDmitry Baryshkov 	.exit		= ptn3222_exit,
49*c9be539eSDmitry Baryshkov 	.owner		= THIS_MODULE,
50*c9be539eSDmitry Baryshkov };
51*c9be539eSDmitry Baryshkov 
52*c9be539eSDmitry Baryshkov static const struct regulator_bulk_data ptn3222_supplies[NUM_SUPPLIES] = {
53*c9be539eSDmitry Baryshkov 	{
54*c9be539eSDmitry Baryshkov 		.supply = "vdd3v3",
55*c9be539eSDmitry Baryshkov 		.init_load_uA = 11000,
56*c9be539eSDmitry Baryshkov 	}, {
57*c9be539eSDmitry Baryshkov 		.supply = "vdd1v8",
58*c9be539eSDmitry Baryshkov 		.init_load_uA = 55000,
59*c9be539eSDmitry Baryshkov 	}
60*c9be539eSDmitry Baryshkov };
61*c9be539eSDmitry Baryshkov 
62*c9be539eSDmitry Baryshkov static int ptn3222_probe(struct i2c_client *client)
63*c9be539eSDmitry Baryshkov {
64*c9be539eSDmitry Baryshkov 	struct device *dev = &client->dev;
65*c9be539eSDmitry Baryshkov 	struct phy_provider *phy_provider;
66*c9be539eSDmitry Baryshkov 	struct ptn3222 *ptn3222;
67*c9be539eSDmitry Baryshkov 	int ret;
68*c9be539eSDmitry Baryshkov 
69*c9be539eSDmitry Baryshkov 	ptn3222 = devm_kzalloc(dev, sizeof(*ptn3222), GFP_KERNEL);
70*c9be539eSDmitry Baryshkov 	if (!ptn3222)
71*c9be539eSDmitry Baryshkov 		return -ENOMEM;
72*c9be539eSDmitry Baryshkov 
73*c9be539eSDmitry Baryshkov 	ptn3222->client = client;
74*c9be539eSDmitry Baryshkov 
75*c9be539eSDmitry Baryshkov 	ptn3222->reset_gpio = devm_gpiod_get_optional(dev, "reset",
76*c9be539eSDmitry Baryshkov 						      GPIOD_OUT_HIGH);
77*c9be539eSDmitry Baryshkov 	if (IS_ERR(ptn3222->reset_gpio))
78*c9be539eSDmitry Baryshkov 		return dev_err_probe(dev, PTR_ERR(ptn3222->reset_gpio),
79*c9be539eSDmitry Baryshkov 				     "unable to acquire reset gpio\n");
80*c9be539eSDmitry Baryshkov 
81*c9be539eSDmitry Baryshkov 	ret = devm_regulator_bulk_get_const(dev, NUM_SUPPLIES, ptn3222_supplies,
82*c9be539eSDmitry Baryshkov 					    &ptn3222->supplies);
83*c9be539eSDmitry Baryshkov 	if (ret)
84*c9be539eSDmitry Baryshkov 		return ret;
85*c9be539eSDmitry Baryshkov 
86*c9be539eSDmitry Baryshkov 	ptn3222->phy = devm_phy_create(dev, dev->of_node, &ptn3222_ops);
87*c9be539eSDmitry Baryshkov 	if (IS_ERR(ptn3222->phy)) {
88*c9be539eSDmitry Baryshkov 		dev_err(dev, "failed to create PHY: %d\n", ret);
89*c9be539eSDmitry Baryshkov 		return PTR_ERR(ptn3222->phy);
90*c9be539eSDmitry Baryshkov 	}
91*c9be539eSDmitry Baryshkov 
92*c9be539eSDmitry Baryshkov 	phy_set_drvdata(ptn3222->phy, ptn3222);
93*c9be539eSDmitry Baryshkov 
94*c9be539eSDmitry Baryshkov 	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
95*c9be539eSDmitry Baryshkov 
96*c9be539eSDmitry Baryshkov 	return PTR_ERR_OR_ZERO(phy_provider);
97*c9be539eSDmitry Baryshkov }
98*c9be539eSDmitry Baryshkov 
99*c9be539eSDmitry Baryshkov static const struct i2c_device_id ptn3222_table[] = {
100*c9be539eSDmitry Baryshkov 	{ "ptn3222" },
101*c9be539eSDmitry Baryshkov 	{ }
102*c9be539eSDmitry Baryshkov };
103*c9be539eSDmitry Baryshkov MODULE_DEVICE_TABLE(i2c, ptn3222_table);
104*c9be539eSDmitry Baryshkov 
105*c9be539eSDmitry Baryshkov static const struct of_device_id ptn3222_of_table[] = {
106*c9be539eSDmitry Baryshkov 	{ .compatible = "nxp,ptn3222" },
107*c9be539eSDmitry Baryshkov 	{ }
108*c9be539eSDmitry Baryshkov };
109*c9be539eSDmitry Baryshkov MODULE_DEVICE_TABLE(of, ptn3222_of_table);
110*c9be539eSDmitry Baryshkov 
111*c9be539eSDmitry Baryshkov static struct i2c_driver ptn3222_driver = {
112*c9be539eSDmitry Baryshkov 	.driver = {
113*c9be539eSDmitry Baryshkov 		.name = "ptn3222",
114*c9be539eSDmitry Baryshkov 		.of_match_table = ptn3222_of_table,
115*c9be539eSDmitry Baryshkov 	},
116*c9be539eSDmitry Baryshkov 	.probe = ptn3222_probe,
117*c9be539eSDmitry Baryshkov 	.id_table = ptn3222_table,
118*c9be539eSDmitry Baryshkov };
119*c9be539eSDmitry Baryshkov 
120*c9be539eSDmitry Baryshkov module_i2c_driver(ptn3222_driver);
121*c9be539eSDmitry Baryshkov 
122*c9be539eSDmitry Baryshkov MODULE_DESCRIPTION("NXP PTN3222 eUSB2 Redriver driver");
123*c9be539eSDmitry Baryshkov MODULE_LICENSE("GPL");
124