136077e16SNeil Armstrong // SPDX-License-Identifier: GPL-2.0 236077e16SNeil Armstrong /* 336077e16SNeil Armstrong * Amlogic G12A USB3 + PCIE Combo PHY driver 436077e16SNeil Armstrong * 536077e16SNeil Armstrong * Copyright (C) 2017 Amlogic, Inc. All rights reserved 636077e16SNeil Armstrong * Copyright (C) 2019 BayLibre, SAS 736077e16SNeil Armstrong * Author: Neil Armstrong <narmstrong@baylibre.com> 836077e16SNeil Armstrong */ 936077e16SNeil Armstrong 1036077e16SNeil Armstrong #include <linux/bitfield.h> 1136077e16SNeil Armstrong #include <linux/bitops.h> 1236077e16SNeil Armstrong #include <linux/clk.h> 1336077e16SNeil Armstrong #include <linux/module.h> 1436077e16SNeil Armstrong #include <linux/of_device.h> 1536077e16SNeil Armstrong #include <linux/phy/phy.h> 1636077e16SNeil Armstrong #include <linux/regmap.h> 1736077e16SNeil Armstrong #include <linux/reset.h> 1836077e16SNeil Armstrong #include <linux/platform_device.h> 1936077e16SNeil Armstrong #include <dt-bindings/phy/phy.h> 2036077e16SNeil Armstrong 2136077e16SNeil Armstrong #define PHY_R0 0x00 2236077e16SNeil Armstrong #define PHY_R0_PCIE_POWER_STATE GENMASK(4, 0) 2336077e16SNeil Armstrong #define PHY_R0_PCIE_USB3_SWITCH GENMASK(6, 5) 2436077e16SNeil Armstrong 2536077e16SNeil Armstrong #define PHY_R1 0x04 2636077e16SNeil Armstrong #define PHY_R1_PHY_TX1_TERM_OFFSET GENMASK(4, 0) 2736077e16SNeil Armstrong #define PHY_R1_PHY_TX0_TERM_OFFSET GENMASK(9, 5) 2836077e16SNeil Armstrong #define PHY_R1_PHY_RX1_EQ GENMASK(12, 10) 2936077e16SNeil Armstrong #define PHY_R1_PHY_RX0_EQ GENMASK(15, 13) 3036077e16SNeil Armstrong #define PHY_R1_PHY_LOS_LEVEL GENMASK(20, 16) 3136077e16SNeil Armstrong #define PHY_R1_PHY_LOS_BIAS GENMASK(23, 21) 3236077e16SNeil Armstrong #define PHY_R1_PHY_REF_CLKDIV2 BIT(24) 3336077e16SNeil Armstrong #define PHY_R1_PHY_MPLL_MULTIPLIER GENMASK(31, 25) 3436077e16SNeil Armstrong 3536077e16SNeil Armstrong #define PHY_R2 0x08 3636077e16SNeil Armstrong #define PHY_R2_PCS_TX_DEEMPH_GEN2_6DB GENMASK(5, 0) 3736077e16SNeil Armstrong #define PHY_R2_PCS_TX_DEEMPH_GEN2_3P5DB GENMASK(11, 6) 3836077e16SNeil Armstrong #define PHY_R2_PCS_TX_DEEMPH_GEN1 GENMASK(17, 12) 3936077e16SNeil Armstrong #define PHY_R2_PHY_TX_VBOOST_LVL GENMASK(20, 18) 4036077e16SNeil Armstrong 4136077e16SNeil Armstrong #define PHY_R4 0x10 4236077e16SNeil Armstrong #define PHY_R4_PHY_CR_WRITE BIT(0) 4336077e16SNeil Armstrong #define PHY_R4_PHY_CR_READ BIT(1) 4436077e16SNeil Armstrong #define PHY_R4_PHY_CR_DATA_IN GENMASK(17, 2) 4536077e16SNeil Armstrong #define PHY_R4_PHY_CR_CAP_DATA BIT(18) 4636077e16SNeil Armstrong #define PHY_R4_PHY_CR_CAP_ADDR BIT(19) 4736077e16SNeil Armstrong 4836077e16SNeil Armstrong #define PHY_R5 0x14 4936077e16SNeil Armstrong #define PHY_R5_PHY_CR_DATA_OUT GENMASK(15, 0) 5036077e16SNeil Armstrong #define PHY_R5_PHY_CR_ACK BIT(16) 5136077e16SNeil Armstrong #define PHY_R5_PHY_BS_OUT BIT(17) 5236077e16SNeil Armstrong 5336077e16SNeil Armstrong struct phy_g12a_usb3_pcie_priv { 5436077e16SNeil Armstrong struct regmap *regmap; 5536077e16SNeil Armstrong struct regmap *regmap_cr; 5636077e16SNeil Armstrong struct clk *clk_ref; 5736077e16SNeil Armstrong struct reset_control *reset; 5836077e16SNeil Armstrong struct phy *phy; 5936077e16SNeil Armstrong unsigned int mode; 6036077e16SNeil Armstrong }; 6136077e16SNeil Armstrong 6236077e16SNeil Armstrong static const struct regmap_config phy_g12a_usb3_pcie_regmap_conf = { 6336077e16SNeil Armstrong .reg_bits = 8, 6436077e16SNeil Armstrong .val_bits = 32, 6536077e16SNeil Armstrong .reg_stride = 4, 6636077e16SNeil Armstrong .max_register = PHY_R5, 6736077e16SNeil Armstrong }; 6836077e16SNeil Armstrong 6936077e16SNeil Armstrong static int phy_g12a_usb3_pcie_cr_bus_addr(struct phy_g12a_usb3_pcie_priv *priv, 7036077e16SNeil Armstrong unsigned int addr) 7136077e16SNeil Armstrong { 7236077e16SNeil Armstrong unsigned int val, reg; 7336077e16SNeil Armstrong int ret; 7436077e16SNeil Armstrong 7536077e16SNeil Armstrong reg = FIELD_PREP(PHY_R4_PHY_CR_DATA_IN, addr); 7636077e16SNeil Armstrong 7736077e16SNeil Armstrong regmap_write(priv->regmap, PHY_R4, reg); 7836077e16SNeil Armstrong regmap_write(priv->regmap, PHY_R4, reg); 7936077e16SNeil Armstrong 8036077e16SNeil Armstrong regmap_write(priv->regmap, PHY_R4, reg | PHY_R4_PHY_CR_CAP_ADDR); 8136077e16SNeil Armstrong 8236077e16SNeil Armstrong ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val, 8336077e16SNeil Armstrong (val & PHY_R5_PHY_CR_ACK), 8436077e16SNeil Armstrong 5, 1000); 8536077e16SNeil Armstrong if (ret) 8636077e16SNeil Armstrong return ret; 8736077e16SNeil Armstrong 8836077e16SNeil Armstrong regmap_write(priv->regmap, PHY_R4, reg); 8936077e16SNeil Armstrong 9036077e16SNeil Armstrong ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val, 9136077e16SNeil Armstrong !(val & PHY_R5_PHY_CR_ACK), 9236077e16SNeil Armstrong 5, 1000); 9336077e16SNeil Armstrong if (ret) 9436077e16SNeil Armstrong return ret; 9536077e16SNeil Armstrong 9636077e16SNeil Armstrong return 0; 9736077e16SNeil Armstrong } 9836077e16SNeil Armstrong 9936077e16SNeil Armstrong static int phy_g12a_usb3_pcie_cr_bus_read(void *context, unsigned int addr, 10036077e16SNeil Armstrong unsigned int *data) 10136077e16SNeil Armstrong { 10236077e16SNeil Armstrong struct phy_g12a_usb3_pcie_priv *priv = context; 10336077e16SNeil Armstrong unsigned int val; 10436077e16SNeil Armstrong int ret; 10536077e16SNeil Armstrong 10636077e16SNeil Armstrong ret = phy_g12a_usb3_pcie_cr_bus_addr(priv, addr); 10736077e16SNeil Armstrong if (ret) 10836077e16SNeil Armstrong return ret; 10936077e16SNeil Armstrong 11036077e16SNeil Armstrong regmap_write(priv->regmap, PHY_R4, 0); 11136077e16SNeil Armstrong regmap_write(priv->regmap, PHY_R4, PHY_R4_PHY_CR_READ); 11236077e16SNeil Armstrong 11336077e16SNeil Armstrong ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val, 11436077e16SNeil Armstrong (val & PHY_R5_PHY_CR_ACK), 11536077e16SNeil Armstrong 5, 1000); 11636077e16SNeil Armstrong if (ret) 11736077e16SNeil Armstrong return ret; 11836077e16SNeil Armstrong 11936077e16SNeil Armstrong *data = FIELD_GET(PHY_R5_PHY_CR_DATA_OUT, val); 12036077e16SNeil Armstrong 12136077e16SNeil Armstrong regmap_write(priv->regmap, PHY_R4, 0); 12236077e16SNeil Armstrong 12336077e16SNeil Armstrong ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val, 12436077e16SNeil Armstrong !(val & PHY_R5_PHY_CR_ACK), 12536077e16SNeil Armstrong 5, 1000); 12636077e16SNeil Armstrong if (ret) 12736077e16SNeil Armstrong return ret; 12836077e16SNeil Armstrong 12936077e16SNeil Armstrong return 0; 13036077e16SNeil Armstrong } 13136077e16SNeil Armstrong 13236077e16SNeil Armstrong static int phy_g12a_usb3_pcie_cr_bus_write(void *context, unsigned int addr, 13336077e16SNeil Armstrong unsigned int data) 13436077e16SNeil Armstrong { 13536077e16SNeil Armstrong struct phy_g12a_usb3_pcie_priv *priv = context; 13636077e16SNeil Armstrong unsigned int val, reg; 13736077e16SNeil Armstrong int ret; 13836077e16SNeil Armstrong 13936077e16SNeil Armstrong ret = phy_g12a_usb3_pcie_cr_bus_addr(priv, addr); 14036077e16SNeil Armstrong if (ret) 14136077e16SNeil Armstrong return ret; 14236077e16SNeil Armstrong 14336077e16SNeil Armstrong reg = FIELD_PREP(PHY_R4_PHY_CR_DATA_IN, data); 14436077e16SNeil Armstrong 14536077e16SNeil Armstrong regmap_write(priv->regmap, PHY_R4, reg); 14636077e16SNeil Armstrong regmap_write(priv->regmap, PHY_R4, reg); 14736077e16SNeil Armstrong 14836077e16SNeil Armstrong regmap_write(priv->regmap, PHY_R4, reg | PHY_R4_PHY_CR_CAP_DATA); 14936077e16SNeil Armstrong 15036077e16SNeil Armstrong ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val, 15136077e16SNeil Armstrong (val & PHY_R5_PHY_CR_ACK), 15236077e16SNeil Armstrong 5, 1000); 15336077e16SNeil Armstrong if (ret) 15436077e16SNeil Armstrong return ret; 15536077e16SNeil Armstrong 15636077e16SNeil Armstrong regmap_write(priv->regmap, PHY_R4, reg); 15736077e16SNeil Armstrong 15836077e16SNeil Armstrong ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val, 15936077e16SNeil Armstrong (val & PHY_R5_PHY_CR_ACK) == 0, 16036077e16SNeil Armstrong 5, 1000); 16136077e16SNeil Armstrong if (ret) 16236077e16SNeil Armstrong return ret; 16336077e16SNeil Armstrong 16436077e16SNeil Armstrong regmap_write(priv->regmap, PHY_R4, reg); 16536077e16SNeil Armstrong 16636077e16SNeil Armstrong regmap_write(priv->regmap, PHY_R4, reg | PHY_R4_PHY_CR_WRITE); 16736077e16SNeil Armstrong 16836077e16SNeil Armstrong ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val, 16936077e16SNeil Armstrong (val & PHY_R5_PHY_CR_ACK), 17036077e16SNeil Armstrong 5, 1000); 17136077e16SNeil Armstrong if (ret) 17236077e16SNeil Armstrong return ret; 17336077e16SNeil Armstrong 17436077e16SNeil Armstrong regmap_write(priv->regmap, PHY_R4, reg); 17536077e16SNeil Armstrong 17636077e16SNeil Armstrong ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val, 17736077e16SNeil Armstrong (val & PHY_R5_PHY_CR_ACK) == 0, 17836077e16SNeil Armstrong 5, 1000); 17936077e16SNeil Armstrong if (ret) 18036077e16SNeil Armstrong return ret; 18136077e16SNeil Armstrong 18236077e16SNeil Armstrong return 0; 18336077e16SNeil Armstrong } 18436077e16SNeil Armstrong 18536077e16SNeil Armstrong static const struct regmap_config phy_g12a_usb3_pcie_cr_regmap_conf = { 18636077e16SNeil Armstrong .reg_bits = 16, 18736077e16SNeil Armstrong .val_bits = 16, 18836077e16SNeil Armstrong .reg_read = phy_g12a_usb3_pcie_cr_bus_read, 18936077e16SNeil Armstrong .reg_write = phy_g12a_usb3_pcie_cr_bus_write, 19036077e16SNeil Armstrong .max_register = 0xffff, 19136077e16SNeil Armstrong .fast_io = true, 19236077e16SNeil Armstrong }; 19336077e16SNeil Armstrong 19436077e16SNeil Armstrong static int phy_g12a_usb3_init(struct phy *phy) 19536077e16SNeil Armstrong { 19636077e16SNeil Armstrong struct phy_g12a_usb3_pcie_priv *priv = phy_get_drvdata(phy); 19736077e16SNeil Armstrong int data, ret; 19836077e16SNeil Armstrong 19936077e16SNeil Armstrong /* Switch PHY to USB3 */ 20036077e16SNeil Armstrong /* TODO figure out how to handle when PCIe was set in the bootloader */ 20136077e16SNeil Armstrong regmap_update_bits(priv->regmap, PHY_R0, 20236077e16SNeil Armstrong PHY_R0_PCIE_USB3_SWITCH, 20336077e16SNeil Armstrong PHY_R0_PCIE_USB3_SWITCH); 20436077e16SNeil Armstrong 20536077e16SNeil Armstrong /* 20636077e16SNeil Armstrong * WORKAROUND: There is SSPHY suspend bug due to 20736077e16SNeil Armstrong * which USB enumerates 20836077e16SNeil Armstrong * in HS mode instead of SS mode. Workaround it by asserting 20936077e16SNeil Armstrong * LANE0.TX_ALT_BLOCK.EN_ALT_BUS to enable TX to use alt bus 21036077e16SNeil Armstrong * mode 21136077e16SNeil Armstrong */ 21236077e16SNeil Armstrong ret = regmap_update_bits(priv->regmap_cr, 0x102d, BIT(7), BIT(7)); 21336077e16SNeil Armstrong if (ret) 21436077e16SNeil Armstrong return ret; 21536077e16SNeil Armstrong 21636077e16SNeil Armstrong ret = regmap_update_bits(priv->regmap_cr, 0x1010, 0xff0, 20); 21736077e16SNeil Armstrong if (ret) 21836077e16SNeil Armstrong return ret; 21936077e16SNeil Armstrong 22036077e16SNeil Armstrong /* 22136077e16SNeil Armstrong * Fix RX Equalization setting as follows 22236077e16SNeil Armstrong * LANE0.RX_OVRD_IN_HI. RX_EQ_EN set to 0 22336077e16SNeil Armstrong * LANE0.RX_OVRD_IN_HI.RX_EQ_EN_OVRD set to 1 22436077e16SNeil Armstrong * LANE0.RX_OVRD_IN_HI.RX_EQ set to 3 22536077e16SNeil Armstrong * LANE0.RX_OVRD_IN_HI.RX_EQ_OVRD set to 1 22636077e16SNeil Armstrong */ 22736077e16SNeil Armstrong ret = regmap_read(priv->regmap_cr, 0x1006, &data); 22836077e16SNeil Armstrong if (ret) 22936077e16SNeil Armstrong return ret; 23036077e16SNeil Armstrong 23136077e16SNeil Armstrong data &= ~BIT(6); 23236077e16SNeil Armstrong data |= BIT(7); 23336077e16SNeil Armstrong data &= ~(0x7 << 8); 23436077e16SNeil Armstrong data |= (0x3 << 8); 23536077e16SNeil Armstrong data |= (1 << 11); 23636077e16SNeil Armstrong ret = regmap_write(priv->regmap_cr, 0x1006, data); 23736077e16SNeil Armstrong if (ret) 23836077e16SNeil Armstrong return ret; 23936077e16SNeil Armstrong 24036077e16SNeil Armstrong /* 24136077e16SNeil Armstrong * Set EQ and TX launch amplitudes as follows 24236077e16SNeil Armstrong * LANE0.TX_OVRD_DRV_LO.PREEMPH set to 22 24336077e16SNeil Armstrong * LANE0.TX_OVRD_DRV_LO.AMPLITUDE set to 127 24436077e16SNeil Armstrong * LANE0.TX_OVRD_DRV_LO.EN set to 1. 24536077e16SNeil Armstrong */ 24636077e16SNeil Armstrong ret = regmap_read(priv->regmap_cr, 0x1002, &data); 24736077e16SNeil Armstrong if (ret) 24836077e16SNeil Armstrong return ret; 24936077e16SNeil Armstrong 25036077e16SNeil Armstrong data &= ~0x3f80; 25136077e16SNeil Armstrong data |= (0x16 << 7); 25236077e16SNeil Armstrong data &= ~0x7f; 25336077e16SNeil Armstrong data |= (0x7f | BIT(14)); 25436077e16SNeil Armstrong ret = regmap_write(priv->regmap_cr, 0x1002, data); 25536077e16SNeil Armstrong if (ret) 25636077e16SNeil Armstrong return ret; 25736077e16SNeil Armstrong 25836077e16SNeil Armstrong /* MPLL_LOOP_CTL.PROP_CNTRL = 8 */ 25936077e16SNeil Armstrong ret = regmap_update_bits(priv->regmap_cr, 0x30, 0xf << 4, 8 << 4); 26036077e16SNeil Armstrong if (ret) 26136077e16SNeil Armstrong return ret; 26236077e16SNeil Armstrong 26336077e16SNeil Armstrong regmap_update_bits(priv->regmap, PHY_R2, 26436077e16SNeil Armstrong PHY_R2_PHY_TX_VBOOST_LVL, 26536077e16SNeil Armstrong FIELD_PREP(PHY_R2_PHY_TX_VBOOST_LVL, 0x4)); 26636077e16SNeil Armstrong 26736077e16SNeil Armstrong regmap_update_bits(priv->regmap, PHY_R1, 26836077e16SNeil Armstrong PHY_R1_PHY_LOS_BIAS | PHY_R1_PHY_LOS_LEVEL, 26936077e16SNeil Armstrong FIELD_PREP(PHY_R1_PHY_LOS_BIAS, 4) | 27036077e16SNeil Armstrong FIELD_PREP(PHY_R1_PHY_LOS_LEVEL, 9)); 27136077e16SNeil Armstrong 27236077e16SNeil Armstrong return 0; 27336077e16SNeil Armstrong } 27436077e16SNeil Armstrong 27536077e16SNeil Armstrong static int phy_g12a_usb3_pcie_init(struct phy *phy) 27636077e16SNeil Armstrong { 27736077e16SNeil Armstrong struct phy_g12a_usb3_pcie_priv *priv = phy_get_drvdata(phy); 27836077e16SNeil Armstrong int ret; 27936077e16SNeil Armstrong 28036077e16SNeil Armstrong ret = reset_control_reset(priv->reset); 28136077e16SNeil Armstrong if (ret) 28236077e16SNeil Armstrong return ret; 28336077e16SNeil Armstrong 28436077e16SNeil Armstrong if (priv->mode == PHY_TYPE_USB3) 28536077e16SNeil Armstrong return phy_g12a_usb3_init(phy); 28636077e16SNeil Armstrong 28736077e16SNeil Armstrong /* Power UP PCIE */ 28836077e16SNeil Armstrong /* TODO figure out when the bootloader has set USB3 mode before */ 28936077e16SNeil Armstrong regmap_update_bits(priv->regmap, PHY_R0, 29036077e16SNeil Armstrong PHY_R0_PCIE_POWER_STATE, 29136077e16SNeil Armstrong FIELD_PREP(PHY_R0_PCIE_POWER_STATE, 0x1c)); 29236077e16SNeil Armstrong 29336077e16SNeil Armstrong return 0; 29436077e16SNeil Armstrong } 29536077e16SNeil Armstrong 29636077e16SNeil Armstrong static int phy_g12a_usb3_pcie_exit(struct phy *phy) 29736077e16SNeil Armstrong { 29836077e16SNeil Armstrong struct phy_g12a_usb3_pcie_priv *priv = phy_get_drvdata(phy); 29936077e16SNeil Armstrong 30036077e16SNeil Armstrong return reset_control_reset(priv->reset); 30136077e16SNeil Armstrong } 30236077e16SNeil Armstrong 30336077e16SNeil Armstrong static struct phy *phy_g12a_usb3_pcie_xlate(struct device *dev, 30436077e16SNeil Armstrong struct of_phandle_args *args) 30536077e16SNeil Armstrong { 30636077e16SNeil Armstrong struct phy_g12a_usb3_pcie_priv *priv = dev_get_drvdata(dev); 30736077e16SNeil Armstrong unsigned int mode; 30836077e16SNeil Armstrong 30936077e16SNeil Armstrong if (args->args_count < 1) { 31036077e16SNeil Armstrong dev_err(dev, "invalid number of arguments\n"); 31136077e16SNeil Armstrong return ERR_PTR(-EINVAL); 31236077e16SNeil Armstrong } 31336077e16SNeil Armstrong 31436077e16SNeil Armstrong mode = args->args[0]; 31536077e16SNeil Armstrong 31636077e16SNeil Armstrong if (mode != PHY_TYPE_USB3 && mode != PHY_TYPE_PCIE) { 31736077e16SNeil Armstrong dev_err(dev, "invalid phy mode select argument\n"); 31836077e16SNeil Armstrong return ERR_PTR(-EINVAL); 31936077e16SNeil Armstrong } 32036077e16SNeil Armstrong 32136077e16SNeil Armstrong priv->mode = mode; 32236077e16SNeil Armstrong 32336077e16SNeil Armstrong return priv->phy; 32436077e16SNeil Armstrong } 32536077e16SNeil Armstrong 32636077e16SNeil Armstrong static const struct phy_ops phy_g12a_usb3_pcie_ops = { 32736077e16SNeil Armstrong .init = phy_g12a_usb3_pcie_init, 32836077e16SNeil Armstrong .exit = phy_g12a_usb3_pcie_exit, 32936077e16SNeil Armstrong .owner = THIS_MODULE, 33036077e16SNeil Armstrong }; 33136077e16SNeil Armstrong 33236077e16SNeil Armstrong static int phy_g12a_usb3_pcie_probe(struct platform_device *pdev) 33336077e16SNeil Armstrong { 33436077e16SNeil Armstrong struct device *dev = &pdev->dev; 33536077e16SNeil Armstrong struct device_node *np = dev->of_node; 33636077e16SNeil Armstrong struct phy_g12a_usb3_pcie_priv *priv; 33736077e16SNeil Armstrong struct resource *res; 33836077e16SNeil Armstrong struct phy_provider *phy_provider; 33936077e16SNeil Armstrong void __iomem *base; 34036077e16SNeil Armstrong int ret; 34136077e16SNeil Armstrong 34236077e16SNeil Armstrong priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 34336077e16SNeil Armstrong if (!priv) 34436077e16SNeil Armstrong return -ENOMEM; 34536077e16SNeil Armstrong 34636077e16SNeil Armstrong res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 34736077e16SNeil Armstrong base = devm_ioremap_resource(dev, res); 34836077e16SNeil Armstrong if (IS_ERR(base)) 34936077e16SNeil Armstrong return PTR_ERR(base); 35036077e16SNeil Armstrong 35136077e16SNeil Armstrong priv->regmap = devm_regmap_init_mmio(dev, base, 35236077e16SNeil Armstrong &phy_g12a_usb3_pcie_regmap_conf); 35336077e16SNeil Armstrong if (IS_ERR(priv->regmap)) 35436077e16SNeil Armstrong return PTR_ERR(priv->regmap); 35536077e16SNeil Armstrong 35636077e16SNeil Armstrong priv->regmap_cr = devm_regmap_init(dev, NULL, priv, 35736077e16SNeil Armstrong &phy_g12a_usb3_pcie_cr_regmap_conf); 35836077e16SNeil Armstrong if (IS_ERR(priv->regmap_cr)) 35936077e16SNeil Armstrong return PTR_ERR(priv->regmap_cr); 36036077e16SNeil Armstrong 36136077e16SNeil Armstrong priv->clk_ref = devm_clk_get(dev, "ref_clk"); 36236077e16SNeil Armstrong if (IS_ERR(priv->clk_ref)) 36336077e16SNeil Armstrong return PTR_ERR(priv->clk_ref); 36436077e16SNeil Armstrong 36536077e16SNeil Armstrong ret = clk_prepare_enable(priv->clk_ref); 36636077e16SNeil Armstrong if (ret) 36736077e16SNeil Armstrong goto err_disable_clk_ref; 36836077e16SNeil Armstrong 36936077e16SNeil Armstrong priv->reset = devm_reset_control_array_get(dev, false, false); 37036077e16SNeil Armstrong if (IS_ERR(priv->reset)) 37136077e16SNeil Armstrong return PTR_ERR(priv->reset); 37236077e16SNeil Armstrong 37336077e16SNeil Armstrong priv->phy = devm_phy_create(dev, np, &phy_g12a_usb3_pcie_ops); 37436077e16SNeil Armstrong if (IS_ERR(priv->phy)) { 37536077e16SNeil Armstrong ret = PTR_ERR(priv->phy); 37636077e16SNeil Armstrong if (ret != -EPROBE_DEFER) 37736077e16SNeil Armstrong dev_err(dev, "failed to create PHY\n"); 37836077e16SNeil Armstrong 37936077e16SNeil Armstrong return ret; 38036077e16SNeil Armstrong } 38136077e16SNeil Armstrong 38236077e16SNeil Armstrong phy_set_drvdata(priv->phy, priv); 38336077e16SNeil Armstrong dev_set_drvdata(dev, priv); 38436077e16SNeil Armstrong 38536077e16SNeil Armstrong phy_provider = devm_of_phy_provider_register(dev, 38636077e16SNeil Armstrong phy_g12a_usb3_pcie_xlate); 38736077e16SNeil Armstrong 38836077e16SNeil Armstrong return PTR_ERR_OR_ZERO(phy_provider); 38936077e16SNeil Armstrong 39036077e16SNeil Armstrong err_disable_clk_ref: 39136077e16SNeil Armstrong clk_disable_unprepare(priv->clk_ref); 39236077e16SNeil Armstrong 39336077e16SNeil Armstrong return ret; 39436077e16SNeil Armstrong } 39536077e16SNeil Armstrong 39636077e16SNeil Armstrong static const struct of_device_id phy_g12a_usb3_pcie_of_match[] = { 39736077e16SNeil Armstrong { .compatible = "amlogic,g12a-usb3-pcie-phy", }, 39836077e16SNeil Armstrong { }, 39936077e16SNeil Armstrong }; 40036077e16SNeil Armstrong MODULE_DEVICE_TABLE(of, phy_g12a_usb3_pcie_of_match); 40136077e16SNeil Armstrong 40236077e16SNeil Armstrong static struct platform_driver phy_g12a_usb3_pcie_driver = { 40336077e16SNeil Armstrong .probe = phy_g12a_usb3_pcie_probe, 40436077e16SNeil Armstrong .driver = { 40536077e16SNeil Armstrong .name = "phy-g12a-usb3-pcie", 40636077e16SNeil Armstrong .of_match_table = phy_g12a_usb3_pcie_of_match, 40736077e16SNeil Armstrong }, 40836077e16SNeil Armstrong }; 40936077e16SNeil Armstrong module_platform_driver(phy_g12a_usb3_pcie_driver); 41036077e16SNeil Armstrong 41136077e16SNeil Armstrong MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>"); 41236077e16SNeil Armstrong MODULE_DESCRIPTION("Amlogic G12A USB3 + PCIE Combo PHY driver"); 41336077e16SNeil Armstrong MODULE_LICENSE("GPL v2"); 414