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