Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

phy: freescale: imx8mq-usb: add support for imx8mp usb phy

Add initial support for imx8mp usb phy support, imx8mp usb has
a silimar phy as imx8mq, which has some different customizations
on clock and low power design when SoC integration.

Signed-off-by: Li Jun <jun.li@nxp.com>
Link: https://lore.kernel.org/r/1598276014-2377-2-git-send-email-jun.li@nxp.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Li Jun and committed by
Vinod Koul
4708ee37 e8bd1cd9

+70 -7
+70 -7
drivers/phy/freescale/phy-fsl-imx8mq-usb.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0+ 2 2 /* Copyright (c) 2017 NXP. */ 3 3 4 + #include <linux/bitfield.h> 4 5 #include <linux/clk.h> 6 + #include <linux/delay.h> 5 7 #include <linux/io.h> 6 8 #include <linux/module.h> 9 + #include <linux/of_platform.h> 7 10 #include <linux/phy/phy.h> 8 11 #include <linux/platform_device.h> 9 12 #include <linux/regulator/consumer.h> 10 13 11 14 #define PHY_CTRL0 0x0 12 15 #define PHY_CTRL0_REF_SSP_EN BIT(2) 16 + #define PHY_CTRL0_FSEL_MASK GENMASK(10, 5) 17 + #define PHY_CTRL0_FSEL_24M 0x2a 13 18 14 19 #define PHY_CTRL1 0x4 15 20 #define PHY_CTRL1_RESET BIT(0) ··· 25 20 26 21 #define PHY_CTRL2 0x8 27 22 #define PHY_CTRL2_TXENABLEN0 BIT(8) 23 + #define PHY_CTRL2_OTG_DISABLE BIT(9) 24 + 25 + #define PHY_CTRL6 0x18 26 + #define PHY_CTRL6_ALT_CLK_EN BIT(1) 27 + #define PHY_CTRL6_ALT_CLK_SEL BIT(0) 28 28 29 29 struct imx8mq_usb_phy { 30 30 struct phy *phy; ··· 56 46 value = readl(imx_phy->base + PHY_CTRL2); 57 47 value |= PHY_CTRL2_TXENABLEN0; 58 48 writel(value, imx_phy->base + PHY_CTRL2); 49 + 50 + value = readl(imx_phy->base + PHY_CTRL1); 51 + value &= ~(PHY_CTRL1_RESET | PHY_CTRL1_ATERESET); 52 + writel(value, imx_phy->base + PHY_CTRL1); 53 + 54 + return 0; 55 + } 56 + 57 + static int imx8mp_usb_phy_init(struct phy *phy) 58 + { 59 + struct imx8mq_usb_phy *imx_phy = phy_get_drvdata(phy); 60 + u32 value; 61 + 62 + /* USB3.0 PHY signal fsel for 24M ref */ 63 + value = readl(imx_phy->base + PHY_CTRL0); 64 + value &= ~PHY_CTRL0_FSEL_MASK; 65 + value |= FIELD_PREP(PHY_CTRL0_FSEL_MASK, PHY_CTRL0_FSEL_24M); 66 + writel(value, imx_phy->base + PHY_CTRL0); 67 + 68 + /* Disable alt_clk_en and use internal MPLL clocks */ 69 + value = readl(imx_phy->base + PHY_CTRL6); 70 + value &= ~(PHY_CTRL6_ALT_CLK_SEL | PHY_CTRL6_ALT_CLK_EN); 71 + writel(value, imx_phy->base + PHY_CTRL6); 72 + 73 + value = readl(imx_phy->base + PHY_CTRL1); 74 + value &= ~(PHY_CTRL1_VDATSRCENB0 | PHY_CTRL1_VDATDETENB0); 75 + value |= PHY_CTRL1_RESET | PHY_CTRL1_ATERESET; 76 + writel(value, imx_phy->base + PHY_CTRL1); 77 + 78 + value = readl(imx_phy->base + PHY_CTRL0); 79 + value |= PHY_CTRL0_REF_SSP_EN; 80 + writel(value, imx_phy->base + PHY_CTRL0); 81 + 82 + value = readl(imx_phy->base + PHY_CTRL2); 83 + value |= PHY_CTRL2_TXENABLEN0 | PHY_CTRL2_OTG_DISABLE; 84 + writel(value, imx_phy->base + PHY_CTRL2); 85 + 86 + udelay(10); 59 87 60 88 value = readl(imx_phy->base + PHY_CTRL1); 61 89 value &= ~(PHY_CTRL1_RESET | PHY_CTRL1_ATERESET); ··· 131 83 .owner = THIS_MODULE, 132 84 }; 133 85 86 + static struct phy_ops imx8mp_usb_phy_ops = { 87 + .init = imx8mp_usb_phy_init, 88 + .power_on = imx8mq_phy_power_on, 89 + .power_off = imx8mq_phy_power_off, 90 + .owner = THIS_MODULE, 91 + }; 92 + 93 + static const struct of_device_id imx8mq_usb_phy_of_match[] = { 94 + {.compatible = "fsl,imx8mq-usb-phy", 95 + .data = &imx8mq_usb_phy_ops,}, 96 + {.compatible = "fsl,imx8mp-usb-phy", 97 + .data = &imx8mp_usb_phy_ops,}, 98 + { } 99 + }; 100 + MODULE_DEVICE_TABLE(of, imx8mq_usb_phy_of_match); 101 + 134 102 static int imx8mq_usb_phy_probe(struct platform_device *pdev) 135 103 { 136 104 struct phy_provider *phy_provider; 137 105 struct device *dev = &pdev->dev; 138 106 struct imx8mq_usb_phy *imx_phy; 139 107 struct resource *res; 108 + const struct phy_ops *phy_ops; 140 109 141 110 imx_phy = devm_kzalloc(dev, sizeof(*imx_phy), GFP_KERNEL); 142 111 if (!imx_phy) ··· 170 105 if (IS_ERR(imx_phy->base)) 171 106 return PTR_ERR(imx_phy->base); 172 107 173 - imx_phy->phy = devm_phy_create(dev, NULL, &imx8mq_usb_phy_ops); 108 + phy_ops = of_device_get_match_data(dev); 109 + if (!phy_ops) 110 + return -EINVAL; 111 + 112 + imx_phy->phy = devm_phy_create(dev, NULL, phy_ops); 174 113 if (IS_ERR(imx_phy->phy)) 175 114 return PTR_ERR(imx_phy->phy); 176 115 ··· 188 119 189 120 return PTR_ERR_OR_ZERO(phy_provider); 190 121 } 191 - 192 - static const struct of_device_id imx8mq_usb_phy_of_match[] = { 193 - {.compatible = "fsl,imx8mq-usb-phy",}, 194 - { }, 195 - }; 196 - MODULE_DEVICE_TABLE(of, imx8mq_usb_phy_of_match); 197 122 198 123 static struct platform_driver imx8mq_usb_phy_driver = { 199 124 .probe = imx8mq_usb_phy_probe,