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