phy: add NXP PTN3222 eUSB2 to USB2 redriver

The NXP PTN3222 is the single-port eUSB2 to USB2 redriver that performs
translation between eUSB2 and USB2 signalling schemes. It supports all
three data rates: Low Speed, Full Speed and High Speed.

The reset state enables autonegotiation of the PHY role and of the data
rate, so no additional programming is required.

Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Tested-by: Konrad Dybcio <konradybcio@kernel.org>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Reviewed-by: Stephan Gerhold <stephan.gerhold@linaro.org>
Tested-by: Stephan Gerhold <stephan.gerhold@linaro.org>
Link: https://lore.kernel.org/r/20240830-nxp-ptn3222-v2-2-4c6d8535cf6c@linaro.org
Signed-off-by: Vinod Koul <vkoul@kernel.org>
This commit is contained in:
Dmitry Baryshkov 2024-08-30 11:20:46 +03:00 committed by Vinod Koul
parent 2df490e737
commit c9be539e11
3 changed files with 135 additions and 0 deletions

View File

@ -82,6 +82,17 @@ config PHY_AIROHA_PCIE
This driver create the basic PHY instance and provides initialize This driver create the basic PHY instance and provides initialize
callback for PCIe GEN3 port. callback for PCIe GEN3 port.
config PHY_NXP_PTN3222
tristate "NXP PTN3222 1-port eUSB2 to USB2 redriver"
depends on I2C
depends on OF
select GENERIC_PHY
help
Enable this to support NXP PTN3222 1-port eUSB2 to USB2 Redriver.
This redriver performs translation between eUSB2 and USB2 signalling
schemes. It supports all three USB 2.0 data rates: Low Speed, Full
Speed and High Speed.
source "drivers/phy/allwinner/Kconfig" source "drivers/phy/allwinner/Kconfig"
source "drivers/phy/amlogic/Kconfig" source "drivers/phy/amlogic/Kconfig"
source "drivers/phy/broadcom/Kconfig" source "drivers/phy/broadcom/Kconfig"

View File

@ -11,6 +11,7 @@ obj-$(CONFIG_PHY_XGENE) += phy-xgene.o
obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o
obj-$(CONFIG_USB_LGM_PHY) += phy-lgm-usb.o obj-$(CONFIG_USB_LGM_PHY) += phy-lgm-usb.o
obj-$(CONFIG_PHY_AIROHA_PCIE) += phy-airoha-pcie.o obj-$(CONFIG_PHY_AIROHA_PCIE) += phy-airoha-pcie.o
obj-$(CONFIG_PHY_NXP_PTN3222) += phy-nxp-ptn3222.o
obj-y += allwinner/ \ obj-y += allwinner/ \
amlogic/ \ amlogic/ \
broadcom/ \ broadcom/ \

View File

@ -0,0 +1,123 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2024, Linaro Limited
*/
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/phy/phy.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#define NUM_SUPPLIES 2
struct ptn3222 {
struct i2c_client *client;
struct phy *phy;
struct gpio_desc *reset_gpio;
struct regulator_bulk_data *supplies;
};
static int ptn3222_init(struct phy *phy)
{
struct ptn3222 *ptn3222 = phy_get_drvdata(phy);
int ret;
ret = regulator_bulk_enable(NUM_SUPPLIES, ptn3222->supplies);
if (ret)
return ret;
gpiod_set_value_cansleep(ptn3222->reset_gpio, 0);
return 0;
}
static int ptn3222_exit(struct phy *phy)
{
struct ptn3222 *ptn3222 = phy_get_drvdata(phy);
gpiod_set_value_cansleep(ptn3222->reset_gpio, 1);
return regulator_bulk_disable(NUM_SUPPLIES, ptn3222->supplies);
}
static const struct phy_ops ptn3222_ops = {
.init = ptn3222_init,
.exit = ptn3222_exit,
.owner = THIS_MODULE,
};
static const struct regulator_bulk_data ptn3222_supplies[NUM_SUPPLIES] = {
{
.supply = "vdd3v3",
.init_load_uA = 11000,
}, {
.supply = "vdd1v8",
.init_load_uA = 55000,
}
};
static int ptn3222_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct phy_provider *phy_provider;
struct ptn3222 *ptn3222;
int ret;
ptn3222 = devm_kzalloc(dev, sizeof(*ptn3222), GFP_KERNEL);
if (!ptn3222)
return -ENOMEM;
ptn3222->client = client;
ptn3222->reset_gpio = devm_gpiod_get_optional(dev, "reset",
GPIOD_OUT_HIGH);
if (IS_ERR(ptn3222->reset_gpio))
return dev_err_probe(dev, PTR_ERR(ptn3222->reset_gpio),
"unable to acquire reset gpio\n");
ret = devm_regulator_bulk_get_const(dev, NUM_SUPPLIES, ptn3222_supplies,
&ptn3222->supplies);
if (ret)
return ret;
ptn3222->phy = devm_phy_create(dev, dev->of_node, &ptn3222_ops);
if (IS_ERR(ptn3222->phy)) {
dev_err(dev, "failed to create PHY: %d\n", ret);
return PTR_ERR(ptn3222->phy);
}
phy_set_drvdata(ptn3222->phy, ptn3222);
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
return PTR_ERR_OR_ZERO(phy_provider);
}
static const struct i2c_device_id ptn3222_table[] = {
{ "ptn3222" },
{ }
};
MODULE_DEVICE_TABLE(i2c, ptn3222_table);
static const struct of_device_id ptn3222_of_table[] = {
{ .compatible = "nxp,ptn3222" },
{ }
};
MODULE_DEVICE_TABLE(of, ptn3222_of_table);
static struct i2c_driver ptn3222_driver = {
.driver = {
.name = "ptn3222",
.of_match_table = ptn3222_of_table,
},
.probe = ptn3222_probe,
.id_table = ptn3222_table,
};
module_i2c_driver(ptn3222_driver);
MODULE_DESCRIPTION("NXP PTN3222 eUSB2 Redriver driver");
MODULE_LICENSE("GPL");