Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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
 16struct ptn3222 {
 17	struct i2c_client *client;
 18	struct phy *phy;
 19	struct gpio_desc *reset_gpio;
 20	struct regulator_bulk_data *supplies;
 21};
 22
 23static 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
 37static 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
 46static const struct phy_ops ptn3222_ops = {
 47	.init		= ptn3222_init,
 48	.exit		= ptn3222_exit,
 49	.owner		= THIS_MODULE,
 50};
 51
 52static 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
 62static 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
 99static const struct i2c_device_id ptn3222_table[] = {
100	{ "ptn3222" },
101	{ }
102};
103MODULE_DEVICE_TABLE(i2c, ptn3222_table);
104
105static const struct of_device_id ptn3222_of_table[] = {
106	{ .compatible = "nxp,ptn3222" },
107	{ }
108};
109MODULE_DEVICE_TABLE(of, ptn3222_of_table);
110
111static 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
120module_i2c_driver(ptn3222_driver);
121
122MODULE_DESCRIPTION("NXP PTN3222 eUSB2 Redriver driver");
123MODULE_LICENSE("GPL");