diff options
Diffstat (limited to 'drivers/phy')
24 files changed, 1975 insertions, 118 deletions
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 64b98d242ea6..cc97c897945a 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig | |||
| @@ -15,6 +15,13 @@ config GENERIC_PHY | |||
| 15 | phy users can obtain reference to the PHY. All the users of this | 15 | phy users can obtain reference to the PHY. All the users of this |
| 16 | framework should select this config. | 16 | framework should select this config. |
| 17 | 17 | ||
| 18 | config PHY_BERLIN_SATA | ||
| 19 | tristate "Marvell Berlin SATA PHY driver" | ||
| 20 | depends on ARCH_BERLIN && HAS_IOMEM && OF | ||
| 21 | select GENERIC_PHY | ||
| 22 | help | ||
| 23 | Enable this to support the SATA PHY on Marvell Berlin SoCs. | ||
| 24 | |||
| 18 | config PHY_EXYNOS_MIPI_VIDEO | 25 | config PHY_EXYNOS_MIPI_VIDEO |
| 19 | tristate "S5P/EXYNOS SoC series MIPI CSI-2/DSI PHY driver" | 26 | tristate "S5P/EXYNOS SoC series MIPI CSI-2/DSI PHY driver" |
| 20 | depends on HAS_IOMEM | 27 | depends on HAS_IOMEM |
| @@ -27,10 +34,20 @@ config PHY_EXYNOS_MIPI_VIDEO | |||
| 27 | 34 | ||
| 28 | config PHY_MVEBU_SATA | 35 | config PHY_MVEBU_SATA |
| 29 | def_bool y | 36 | def_bool y |
| 30 | depends on ARCH_KIRKWOOD || ARCH_DOVE || MACH_DOVE || MACH_KIRKWOOD | 37 | depends on ARCH_DOVE || MACH_DOVE || MACH_KIRKWOOD |
| 31 | depends on OF | 38 | depends on OF |
| 32 | select GENERIC_PHY | 39 | select GENERIC_PHY |
| 33 | 40 | ||
| 41 | config PHY_MIPHY365X | ||
| 42 | tristate "STMicroelectronics MIPHY365X PHY driver for STiH41x series" | ||
| 43 | depends on ARCH_STI | ||
| 44 | depends on GENERIC_PHY | ||
| 45 | depends on HAS_IOMEM | ||
| 46 | depends on OF | ||
| 47 | help | ||
| 48 | Enable this to support the miphy transceiver (for SATA/PCIE) | ||
| 49 | that is part of STMicroelectronics STiH41x SoC series. | ||
| 50 | |||
| 34 | config OMAP_CONTROL_PHY | 51 | config OMAP_CONTROL_PHY |
| 35 | tristate "OMAP CONTROL PHY Driver" | 52 | tristate "OMAP CONTROL PHY Driver" |
| 36 | depends on ARCH_OMAP2PLUS || COMPILE_TEST | 53 | depends on ARCH_OMAP2PLUS || COMPILE_TEST |
| @@ -109,6 +126,14 @@ config PHY_EXYNOS5250_SATA | |||
| 109 | SATA 3.0 Gb/s, SATA 6.0 Gb/s speeds. It supports one SATA host | 126 | SATA 3.0 Gb/s, SATA 6.0 Gb/s speeds. It supports one SATA host |
| 110 | port to accept one SATA device. | 127 | port to accept one SATA device. |
| 111 | 128 | ||
| 129 | config PHY_HIX5HD2_SATA | ||
| 130 | tristate "HIX5HD2 SATA PHY Driver" | ||
| 131 | depends on ARCH_HIX5HD2 && OF && HAS_IOMEM | ||
| 132 | select GENERIC_PHY | ||
| 133 | select MFD_SYSCON | ||
| 134 | help | ||
| 135 | Support for SATA PHY on Hisilicon hix5hd2 Soc. | ||
| 136 | |||
| 112 | config PHY_SUN4I_USB | 137 | config PHY_SUN4I_USB |
| 113 | tristate "Allwinner sunxi SoC USB PHY driver" | 138 | tristate "Allwinner sunxi SoC USB PHY driver" |
| 114 | depends on ARCH_SUNXI && HAS_IOMEM && OF | 139 | depends on ARCH_SUNXI && HAS_IOMEM && OF |
| @@ -124,50 +149,39 @@ config PHY_SUN4I_USB | |||
| 124 | config PHY_SAMSUNG_USB2 | 149 | config PHY_SAMSUNG_USB2 |
| 125 | tristate "Samsung USB 2.0 PHY driver" | 150 | tristate "Samsung USB 2.0 PHY driver" |
| 126 | depends on HAS_IOMEM | 151 | depends on HAS_IOMEM |
| 152 | depends on USB_EHCI_EXYNOS || USB_OHCI_EXYNOS || USB_DWC2 | ||
| 127 | select GENERIC_PHY | 153 | select GENERIC_PHY |
| 128 | select MFD_SYSCON | 154 | select MFD_SYSCON |
| 155 | default ARCH_EXYNOS | ||
| 129 | help | 156 | help |
| 130 | Enable this to support the Samsung USB 2.0 PHY driver for Samsung | 157 | Enable this to support the Samsung USB 2.0 PHY driver for Samsung |
| 131 | SoCs. This driver provides the interface for USB 2.0 PHY. Support for | 158 | SoCs. This driver provides the interface for USB 2.0 PHY. Support |
| 132 | particular SoCs has to be enabled in addition to this driver. Number | 159 | for particular PHYs will be enabled based on the SoC type in addition |
| 133 | and type of supported phys depends on the SoC. | 160 | to this driver. |
| 134 | 161 | ||
| 135 | config PHY_EXYNOS4210_USB2 | 162 | config PHY_EXYNOS4210_USB2 |
| 136 | bool "Support for Exynos 4210" | 163 | bool |
| 137 | depends on PHY_SAMSUNG_USB2 | 164 | depends on PHY_SAMSUNG_USB2 |
| 138 | depends on CPU_EXYNOS4210 | 165 | default CPU_EXYNOS4210 |
| 139 | help | ||
| 140 | Enable USB PHY support for Exynos 4210. This option requires that | ||
| 141 | Samsung USB 2.0 PHY driver is enabled and means that support for this | ||
| 142 | particular SoC is compiled in the driver. In case of Exynos 4210 four | ||
| 143 | phys are available - device, host, HSIC0 and HSIC1. | ||
| 144 | 166 | ||
| 145 | config PHY_EXYNOS4X12_USB2 | 167 | config PHY_EXYNOS4X12_USB2 |
| 146 | bool "Support for Exynos 4x12" | 168 | bool |
| 147 | depends on PHY_SAMSUNG_USB2 | 169 | depends on PHY_SAMSUNG_USB2 |
| 148 | depends on (SOC_EXYNOS4212 || SOC_EXYNOS4412) | 170 | default SOC_EXYNOS3250 || SOC_EXYNOS4212 || SOC_EXYNOS4412 |
| 149 | help | ||
| 150 | Enable USB PHY support for Exynos 4x12. This option requires that | ||
| 151 | Samsung USB 2.0 PHY driver is enabled and means that support for this | ||
| 152 | particular SoC is compiled in the driver. In case of Exynos 4x12 four | ||
| 153 | phys are available - device, host, HSIC0 and HSIC1. | ||
| 154 | 171 | ||
| 155 | config PHY_EXYNOS5250_USB2 | 172 | config PHY_EXYNOS5250_USB2 |
| 156 | bool "Support for Exynos 5250" | 173 | bool |
| 157 | depends on PHY_SAMSUNG_USB2 | 174 | depends on PHY_SAMSUNG_USB2 |
| 158 | depends on SOC_EXYNOS5250 | 175 | default SOC_EXYNOS5250 || SOC_EXYNOS5420 |
| 159 | help | ||
| 160 | Enable USB PHY support for Exynos 5250. This option requires that | ||
| 161 | Samsung USB 2.0 PHY driver is enabled and means that support for this | ||
| 162 | particular SoC is compiled in the driver. In case of Exynos 5250 four | ||
| 163 | phys are available - device, host, HSIC0 and HSIC. | ||
| 164 | 176 | ||
| 165 | config PHY_EXYNOS5_USBDRD | 177 | config PHY_EXYNOS5_USBDRD |
| 166 | tristate "Exynos5 SoC series USB DRD PHY driver" | 178 | tristate "Exynos5 SoC series USB DRD PHY driver" |
| 167 | depends on ARCH_EXYNOS5 && OF | 179 | depends on ARCH_EXYNOS5 && OF |
| 168 | depends on HAS_IOMEM | 180 | depends on HAS_IOMEM |
| 181 | depends on USB_DWC3_EXYNOS | ||
| 169 | select GENERIC_PHY | 182 | select GENERIC_PHY |
| 170 | select MFD_SYSCON | 183 | select MFD_SYSCON |
| 184 | default y | ||
| 171 | help | 185 | help |
| 172 | Enable USB DRD PHY support for Exynos 5 SoC series. | 186 | Enable USB DRD PHY support for Exynos 5 SoC series. |
| 173 | This driver provides PHY interface for USB 3.0 DRD controller | 187 | This driver provides PHY interface for USB 3.0 DRD controller |
| @@ -180,4 +194,18 @@ config PHY_XGENE | |||
| 180 | help | 194 | help |
| 181 | This option enables support for APM X-Gene SoC multi-purpose PHY. | 195 | This option enables support for APM X-Gene SoC multi-purpose PHY. |
| 182 | 196 | ||
| 197 | config PHY_QCOM_APQ8064_SATA | ||
| 198 | tristate "Qualcomm APQ8064 SATA SerDes/PHY driver" | ||
| 199 | depends on ARCH_QCOM | ||
| 200 | depends on HAS_IOMEM | ||
| 201 | depends on OF | ||
| 202 | select GENERIC_PHY | ||
| 203 | |||
| 204 | config PHY_QCOM_IPQ806X_SATA | ||
| 205 | tristate "Qualcomm IPQ806x SATA SerDes/PHY driver" | ||
| 206 | depends on ARCH_QCOM | ||
| 207 | depends on HAS_IOMEM | ||
| 208 | depends on OF | ||
| 209 | select GENERIC_PHY | ||
| 210 | |||
| 183 | endmenu | 211 | endmenu |
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index b4f1d5770601..971ad0aac388 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile | |||
| @@ -3,15 +3,18 @@ | |||
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | obj-$(CONFIG_GENERIC_PHY) += phy-core.o | 5 | obj-$(CONFIG_GENERIC_PHY) += phy-core.o |
| 6 | obj-$(CONFIG_PHY_BERLIN_SATA) += phy-berlin-sata.o | ||
| 6 | obj-$(CONFIG_BCM_KONA_USB2_PHY) += phy-bcm-kona-usb2.o | 7 | obj-$(CONFIG_BCM_KONA_USB2_PHY) += phy-bcm-kona-usb2.o |
| 7 | obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO) += phy-exynos-dp-video.o | 8 | obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO) += phy-exynos-dp-video.o |
| 8 | obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o | 9 | obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o |
| 9 | obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o | 10 | obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o |
| 11 | obj-$(CONFIG_PHY_MIPHY365X) += phy-miphy365x.o | ||
| 10 | obj-$(CONFIG_OMAP_CONTROL_PHY) += phy-omap-control.o | 12 | obj-$(CONFIG_OMAP_CONTROL_PHY) += phy-omap-control.o |
| 11 | obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o | 13 | obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o |
| 12 | obj-$(CONFIG_TI_PIPE3) += phy-ti-pipe3.o | 14 | obj-$(CONFIG_TI_PIPE3) += phy-ti-pipe3.o |
| 13 | obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o | 15 | obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o |
| 14 | obj-$(CONFIG_PHY_EXYNOS5250_SATA) += phy-exynos5250-sata.o | 16 | obj-$(CONFIG_PHY_EXYNOS5250_SATA) += phy-exynos5250-sata.o |
| 17 | obj-$(CONFIG_PHY_HIX5HD2_SATA) += phy-hix5hd2-sata.o | ||
| 15 | obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o | 18 | obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o |
| 16 | obj-$(CONFIG_PHY_SAMSUNG_USB2) += phy-exynos-usb2.o | 19 | obj-$(CONFIG_PHY_SAMSUNG_USB2) += phy-exynos-usb2.o |
| 17 | phy-exynos-usb2-y += phy-samsung-usb2.o | 20 | phy-exynos-usb2-y += phy-samsung-usb2.o |
| @@ -20,3 +23,5 @@ phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4X12_USB2) += phy-exynos4x12-usb2.o | |||
| 20 | phy-exynos-usb2-$(CONFIG_PHY_EXYNOS5250_USB2) += phy-exynos5250-usb2.o | 23 | phy-exynos-usb2-$(CONFIG_PHY_EXYNOS5250_USB2) += phy-exynos5250-usb2.o |
| 21 | obj-$(CONFIG_PHY_EXYNOS5_USBDRD) += phy-exynos5-usbdrd.o | 24 | obj-$(CONFIG_PHY_EXYNOS5_USBDRD) += phy-exynos5-usbdrd.o |
| 22 | obj-$(CONFIG_PHY_XGENE) += phy-xgene.o | 25 | obj-$(CONFIG_PHY_XGENE) += phy-xgene.o |
| 26 | obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o | ||
| 27 | obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o | ||
diff --git a/drivers/phy/phy-bcm-kona-usb2.c b/drivers/phy/phy-bcm-kona-usb2.c index e94f5a6a5645..894fe74c1e44 100644 --- a/drivers/phy/phy-bcm-kona-usb2.c +++ b/drivers/phy/phy-bcm-kona-usb2.c | |||
| @@ -117,7 +117,7 @@ static int bcm_kona_usb2_probe(struct platform_device *pdev) | |||
| 117 | 117 | ||
| 118 | platform_set_drvdata(pdev, phy); | 118 | platform_set_drvdata(pdev, phy); |
| 119 | 119 | ||
| 120 | gphy = devm_phy_create(dev, &ops, NULL); | 120 | gphy = devm_phy_create(dev, NULL, &ops, NULL); |
| 121 | if (IS_ERR(gphy)) | 121 | if (IS_ERR(gphy)) |
| 122 | return PTR_ERR(gphy); | 122 | return PTR_ERR(gphy); |
| 123 | 123 | ||
diff --git a/drivers/phy/phy-berlin-sata.c b/drivers/phy/phy-berlin-sata.c new file mode 100644 index 000000000000..5c3a0424aeb4 --- /dev/null +++ b/drivers/phy/phy-berlin-sata.c | |||
| @@ -0,0 +1,284 @@ | |||
| 1 | /* | ||
| 2 | * Marvell Berlin SATA PHY driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2014 Marvell Technology Group Ltd. | ||
| 5 | * | ||
| 6 | * Antoine Ténart <antoine.tenart@free-electrons.com> | ||
| 7 | * | ||
| 8 | * This file is licensed under the terms of the GNU General Public | ||
| 9 | * License version 2. This program is licensed "as is" without any | ||
| 10 | * warranty of any kind, whether express or implied. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/clk.h> | ||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/phy/phy.h> | ||
| 16 | #include <linux/io.h> | ||
| 17 | #include <linux/platform_device.h> | ||
| 18 | |||
| 19 | #define HOST_VSA_ADDR 0x0 | ||
| 20 | #define HOST_VSA_DATA 0x4 | ||
| 21 | #define PORT_SCR_CTL 0x2c | ||
| 22 | #define PORT_VSR_ADDR 0x78 | ||
| 23 | #define PORT_VSR_DATA 0x7c | ||
| 24 | |||
| 25 | #define CONTROL_REGISTER 0x0 | ||
| 26 | #define MBUS_SIZE_CONTROL 0x4 | ||
| 27 | |||
| 28 | #define POWER_DOWN_PHY0 BIT(6) | ||
| 29 | #define POWER_DOWN_PHY1 BIT(14) | ||
| 30 | #define MBUS_WRITE_REQUEST_SIZE_128 (BIT(2) << 16) | ||
| 31 | #define MBUS_READ_REQUEST_SIZE_128 (BIT(2) << 19) | ||
| 32 | |||
| 33 | #define PHY_BASE 0x200 | ||
| 34 | |||
| 35 | /* register 0x01 */ | ||
| 36 | #define REF_FREF_SEL_25 BIT(0) | ||
| 37 | #define PHY_MODE_SATA (0x0 << 5) | ||
| 38 | |||
| 39 | /* register 0x02 */ | ||
| 40 | #define USE_MAX_PLL_RATE BIT(12) | ||
| 41 | |||
| 42 | /* register 0x23 */ | ||
| 43 | #define DATA_BIT_WIDTH_10 (0x0 << 10) | ||
| 44 | #define DATA_BIT_WIDTH_20 (0x1 << 10) | ||
| 45 | #define DATA_BIT_WIDTH_40 (0x2 << 10) | ||
| 46 | |||
| 47 | /* register 0x25 */ | ||
| 48 | #define PHY_GEN_MAX_1_5 (0x0 << 10) | ||
| 49 | #define PHY_GEN_MAX_3_0 (0x1 << 10) | ||
| 50 | #define PHY_GEN_MAX_6_0 (0x2 << 10) | ||
| 51 | |||
| 52 | struct phy_berlin_desc { | ||
| 53 | struct phy *phy; | ||
| 54 | u32 power_bit; | ||
| 55 | unsigned index; | ||
| 56 | }; | ||
| 57 | |||
| 58 | struct phy_berlin_priv { | ||
| 59 | void __iomem *base; | ||
| 60 | spinlock_t lock; | ||
| 61 | struct clk *clk; | ||
| 62 | struct phy_berlin_desc **phys; | ||
| 63 | unsigned nphys; | ||
| 64 | }; | ||
| 65 | |||
| 66 | static inline void phy_berlin_sata_reg_setbits(void __iomem *ctrl_reg, u32 reg, | ||
| 67 | u32 mask, u32 val) | ||
| 68 | { | ||
| 69 | u32 regval; | ||
| 70 | |||
| 71 | /* select register */ | ||
| 72 | writel(PHY_BASE + reg, ctrl_reg + PORT_VSR_ADDR); | ||
| 73 | |||
| 74 | /* set bits */ | ||
| 75 | regval = readl(ctrl_reg + PORT_VSR_DATA); | ||
| 76 | regval &= ~mask; | ||
| 77 | regval |= val; | ||
| 78 | writel(regval, ctrl_reg + PORT_VSR_DATA); | ||
| 79 | } | ||
| 80 | |||
| 81 | static int phy_berlin_sata_power_on(struct phy *phy) | ||
| 82 | { | ||
| 83 | struct phy_berlin_desc *desc = phy_get_drvdata(phy); | ||
| 84 | struct phy_berlin_priv *priv = dev_get_drvdata(phy->dev.parent); | ||
| 85 | void __iomem *ctrl_reg = priv->base + 0x60 + (desc->index * 0x80); | ||
| 86 | int ret = 0; | ||
| 87 | u32 regval; | ||
| 88 | |||
| 89 | clk_prepare_enable(priv->clk); | ||
| 90 | |||
| 91 | spin_lock(&priv->lock); | ||
| 92 | |||
| 93 | /* Power on PHY */ | ||
| 94 | writel(CONTROL_REGISTER, priv->base + HOST_VSA_ADDR); | ||
| 95 | regval = readl(priv->base + HOST_VSA_DATA); | ||
| 96 | regval &= ~desc->power_bit; | ||
| 97 | writel(regval, priv->base + HOST_VSA_DATA); | ||
| 98 | |||
| 99 | /* Configure MBus */ | ||
| 100 | writel(MBUS_SIZE_CONTROL, priv->base + HOST_VSA_ADDR); | ||
| 101 | regval = readl(priv->base + HOST_VSA_DATA); | ||
| 102 | regval |= MBUS_WRITE_REQUEST_SIZE_128 | MBUS_READ_REQUEST_SIZE_128; | ||
| 103 | writel(regval, priv->base + HOST_VSA_DATA); | ||
| 104 | |||
| 105 | /* set PHY mode and ref freq to 25 MHz */ | ||
| 106 | phy_berlin_sata_reg_setbits(ctrl_reg, 0x1, 0xff, | ||
| 107 | REF_FREF_SEL_25 | PHY_MODE_SATA); | ||
| 108 | |||
| 109 | /* set PHY up to 6 Gbps */ | ||
| 110 | phy_berlin_sata_reg_setbits(ctrl_reg, 0x25, 0xc00, PHY_GEN_MAX_6_0); | ||
| 111 | |||
| 112 | /* set 40 bits width */ | ||
| 113 | phy_berlin_sata_reg_setbits(ctrl_reg, 0x23, 0xc00, DATA_BIT_WIDTH_40); | ||
| 114 | |||
| 115 | /* use max pll rate */ | ||
| 116 | phy_berlin_sata_reg_setbits(ctrl_reg, 0x2, 0x0, USE_MAX_PLL_RATE); | ||
| 117 | |||
| 118 | /* set Gen3 controller speed */ | ||
| 119 | regval = readl(ctrl_reg + PORT_SCR_CTL); | ||
| 120 | regval &= ~GENMASK(7, 4); | ||
| 121 | regval |= 0x30; | ||
| 122 | writel(regval, ctrl_reg + PORT_SCR_CTL); | ||
| 123 | |||
| 124 | spin_unlock(&priv->lock); | ||
| 125 | |||
| 126 | clk_disable_unprepare(priv->clk); | ||
| 127 | |||
| 128 | return ret; | ||
| 129 | } | ||
| 130 | |||
| 131 | static int phy_berlin_sata_power_off(struct phy *phy) | ||
| 132 | { | ||
| 133 | struct phy_berlin_desc *desc = phy_get_drvdata(phy); | ||
| 134 | struct phy_berlin_priv *priv = dev_get_drvdata(phy->dev.parent); | ||
| 135 | u32 regval; | ||
| 136 | |||
| 137 | clk_prepare_enable(priv->clk); | ||
| 138 | |||
| 139 | spin_lock(&priv->lock); | ||
| 140 | |||
| 141 | /* Power down PHY */ | ||
| 142 | writel(CONTROL_REGISTER, priv->base + HOST_VSA_ADDR); | ||
| 143 | regval = readl(priv->base + HOST_VSA_DATA); | ||
| 144 | regval |= desc->power_bit; | ||
| 145 | writel(regval, priv->base + HOST_VSA_DATA); | ||
| 146 | |||
| 147 | spin_unlock(&priv->lock); | ||
| 148 | |||
| 149 | clk_disable_unprepare(priv->clk); | ||
| 150 | |||
| 151 | return 0; | ||
| 152 | } | ||
| 153 | |||
| 154 | static struct phy *phy_berlin_sata_phy_xlate(struct device *dev, | ||
| 155 | struct of_phandle_args *args) | ||
| 156 | { | ||
| 157 | struct phy_berlin_priv *priv = dev_get_drvdata(dev); | ||
| 158 | int i; | ||
| 159 | |||
| 160 | if (WARN_ON(args->args[0] >= priv->nphys)) | ||
| 161 | return ERR_PTR(-ENODEV); | ||
| 162 | |||
| 163 | for (i = 0; i < priv->nphys; i++) { | ||
| 164 | if (priv->phys[i]->index == args->args[0]) | ||
| 165 | break; | ||
| 166 | } | ||
| 167 | |||
| 168 | if (i == priv->nphys) | ||
| 169 | return ERR_PTR(-ENODEV); | ||
| 170 | |||
| 171 | return priv->phys[i]->phy; | ||
| 172 | } | ||
| 173 | |||
| 174 | static struct phy_ops phy_berlin_sata_ops = { | ||
| 175 | .power_on = phy_berlin_sata_power_on, | ||
| 176 | .power_off = phy_berlin_sata_power_off, | ||
| 177 | .owner = THIS_MODULE, | ||
| 178 | }; | ||
| 179 | |||
| 180 | static u32 phy_berlin_power_down_bits[] = { | ||
| 181 | POWER_DOWN_PHY0, | ||
| 182 | POWER_DOWN_PHY1, | ||
| 183 | }; | ||
| 184 | |||
| 185 | static int phy_berlin_sata_probe(struct platform_device *pdev) | ||
| 186 | { | ||
| 187 | struct device *dev = &pdev->dev; | ||
| 188 | struct device_node *child; | ||
| 189 | struct phy *phy; | ||
| 190 | struct phy_provider *phy_provider; | ||
| 191 | struct phy_berlin_priv *priv; | ||
| 192 | struct resource *res; | ||
| 193 | int i = 0; | ||
| 194 | u32 phy_id; | ||
| 195 | |||
| 196 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | ||
| 197 | if (!priv) | ||
| 198 | return -ENOMEM; | ||
| 199 | |||
| 200 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 201 | if (!res) | ||
| 202 | return -EINVAL; | ||
| 203 | |||
| 204 | priv->base = devm_ioremap(dev, res->start, resource_size(res)); | ||
| 205 | if (!priv->base) | ||
| 206 | return -ENOMEM; | ||
| 207 | |||
| 208 | priv->clk = devm_clk_get(dev, NULL); | ||
| 209 | if (IS_ERR(priv->clk)) | ||
| 210 | return PTR_ERR(priv->clk); | ||
| 211 | |||
| 212 | priv->nphys = of_get_child_count(dev->of_node); | ||
| 213 | if (priv->nphys == 0) | ||
| 214 | return -ENODEV; | ||
| 215 | |||
| 216 | priv->phys = devm_kzalloc(dev, priv->nphys * sizeof(*priv->phys), | ||
| 217 | GFP_KERNEL); | ||
| 218 | if (!priv->phys) | ||
| 219 | return -ENOMEM; | ||
| 220 | |||
| 221 | dev_set_drvdata(dev, priv); | ||
| 222 | spin_lock_init(&priv->lock); | ||
| 223 | |||
| 224 | for_each_available_child_of_node(dev->of_node, child) { | ||
| 225 | struct phy_berlin_desc *phy_desc; | ||
| 226 | |||
| 227 | if (of_property_read_u32(child, "reg", &phy_id)) { | ||
| 228 | dev_err(dev, "missing reg property in node %s\n", | ||
| 229 | child->name); | ||
| 230 | return -EINVAL; | ||
| 231 | } | ||
| 232 | |||
| 233 | if (phy_id >= ARRAY_SIZE(phy_berlin_power_down_bits)) { | ||
| 234 | dev_err(dev, "invalid reg in node %s\n", child->name); | ||
| 235 | return -EINVAL; | ||
| 236 | } | ||
| 237 | |||
| 238 | phy_desc = devm_kzalloc(dev, sizeof(*phy_desc), GFP_KERNEL); | ||
| 239 | if (!phy_desc) | ||
| 240 | return -ENOMEM; | ||
| 241 | |||
| 242 | phy = devm_phy_create(dev, NULL, &phy_berlin_sata_ops, NULL); | ||
| 243 | if (IS_ERR(phy)) { | ||
| 244 | dev_err(dev, "failed to create PHY %d\n", phy_id); | ||
| 245 | return PTR_ERR(phy); | ||
| 246 | } | ||
| 247 | |||
| 248 | phy_desc->phy = phy; | ||
| 249 | phy_desc->power_bit = phy_berlin_power_down_bits[phy_id]; | ||
| 250 | phy_desc->index = phy_id; | ||
| 251 | phy_set_drvdata(phy, phy_desc); | ||
| 252 | |||
| 253 | priv->phys[i++] = phy_desc; | ||
| 254 | |||
| 255 | /* Make sure the PHY is off */ | ||
| 256 | phy_berlin_sata_power_off(phy); | ||
| 257 | } | ||
| 258 | |||
| 259 | phy_provider = | ||
| 260 | devm_of_phy_provider_register(dev, phy_berlin_sata_phy_xlate); | ||
| 261 | if (IS_ERR(phy_provider)) | ||
| 262 | return PTR_ERR(phy_provider); | ||
| 263 | |||
| 264 | return 0; | ||
| 265 | } | ||
| 266 | |||
| 267 | static const struct of_device_id phy_berlin_sata_of_match[] = { | ||
| 268 | { .compatible = "marvell,berlin2q-sata-phy" }, | ||
| 269 | { }, | ||
| 270 | }; | ||
| 271 | |||
| 272 | static struct platform_driver phy_berlin_sata_driver = { | ||
| 273 | .probe = phy_berlin_sata_probe, | ||
| 274 | .driver = { | ||
| 275 | .name = "phy-berlin-sata", | ||
| 276 | .owner = THIS_MODULE, | ||
| 277 | .of_match_table = phy_berlin_sata_of_match, | ||
| 278 | }, | ||
| 279 | }; | ||
| 280 | module_platform_driver(phy_berlin_sata_driver); | ||
| 281 | |||
| 282 | MODULE_DESCRIPTION("Marvell Berlin SATA PHY driver"); | ||
| 283 | MODULE_AUTHOR("Antoine Ténart <antoine.tenart@free-electrons.com>"); | ||
| 284 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index 49c446530101..ff5eec5af817 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/phy/phy.h> | 21 | #include <linux/phy/phy.h> |
| 22 | #include <linux/idr.h> | 22 | #include <linux/idr.h> |
| 23 | #include <linux/pm_runtime.h> | 23 | #include <linux/pm_runtime.h> |
| 24 | #include <linux/regulator/consumer.h> | ||
| 24 | 25 | ||
| 25 | static struct class *phy_class; | 26 | static struct class *phy_class; |
| 26 | static DEFINE_MUTEX(phy_provider_mutex); | 27 | static DEFINE_MUTEX(phy_provider_mutex); |
| @@ -86,10 +87,15 @@ static struct phy *phy_lookup(struct device *device, const char *port) | |||
| 86 | static struct phy_provider *of_phy_provider_lookup(struct device_node *node) | 87 | static struct phy_provider *of_phy_provider_lookup(struct device_node *node) |
| 87 | { | 88 | { |
| 88 | struct phy_provider *phy_provider; | 89 | struct phy_provider *phy_provider; |
| 90 | struct device_node *child; | ||
| 89 | 91 | ||
| 90 | list_for_each_entry(phy_provider, &phy_provider_list, list) { | 92 | list_for_each_entry(phy_provider, &phy_provider_list, list) { |
| 91 | if (phy_provider->dev->of_node == node) | 93 | if (phy_provider->dev->of_node == node) |
| 92 | return phy_provider; | 94 | return phy_provider; |
| 95 | |||
| 96 | for_each_child_of_node(phy_provider->dev->of_node, child) | ||
| 97 | if (child == node) | ||
| 98 | return phy_provider; | ||
| 93 | } | 99 | } |
| 94 | 100 | ||
| 95 | return ERR_PTR(-EPROBE_DEFER); | 101 | return ERR_PTR(-EPROBE_DEFER); |
| @@ -226,6 +232,12 @@ int phy_power_on(struct phy *phy) | |||
| 226 | if (!phy) | 232 | if (!phy) |
| 227 | return 0; | 233 | return 0; |
| 228 | 234 | ||
| 235 | if (phy->pwr) { | ||
| 236 | ret = regulator_enable(phy->pwr); | ||
| 237 | if (ret) | ||
| 238 | return ret; | ||
| 239 | } | ||
| 240 | |||
| 229 | ret = phy_pm_runtime_get_sync(phy); | 241 | ret = phy_pm_runtime_get_sync(phy); |
| 230 | if (ret < 0 && ret != -ENOTSUPP) | 242 | if (ret < 0 && ret != -ENOTSUPP) |
| 231 | return ret; | 243 | return ret; |
| @@ -247,6 +259,8 @@ int phy_power_on(struct phy *phy) | |||
| 247 | out: | 259 | out: |
| 248 | mutex_unlock(&phy->mutex); | 260 | mutex_unlock(&phy->mutex); |
| 249 | phy_pm_runtime_put_sync(phy); | 261 | phy_pm_runtime_put_sync(phy); |
| 262 | if (phy->pwr) | ||
| 263 | regulator_disable(phy->pwr); | ||
| 250 | 264 | ||
| 251 | return ret; | 265 | return ret; |
| 252 | } | 266 | } |
| @@ -272,6 +286,9 @@ int phy_power_off(struct phy *phy) | |||
| 272 | mutex_unlock(&phy->mutex); | 286 | mutex_unlock(&phy->mutex); |
| 273 | phy_pm_runtime_put(phy); | 287 | phy_pm_runtime_put(phy); |
| 274 | 288 | ||
| 289 | if (phy->pwr) | ||
| 290 | regulator_disable(phy->pwr); | ||
| 291 | |||
| 275 | return 0; | 292 | return 0; |
| 276 | } | 293 | } |
| 277 | EXPORT_SYMBOL_GPL(phy_power_off); | 294 | EXPORT_SYMBOL_GPL(phy_power_off); |
| @@ -398,13 +415,20 @@ struct phy *of_phy_simple_xlate(struct device *dev, struct of_phandle_args | |||
| 398 | struct phy *phy; | 415 | struct phy *phy; |
| 399 | struct class_dev_iter iter; | 416 | struct class_dev_iter iter; |
| 400 | struct device_node *node = dev->of_node; | 417 | struct device_node *node = dev->of_node; |
| 418 | struct device_node *child; | ||
| 401 | 419 | ||
| 402 | class_dev_iter_init(&iter, phy_class, NULL, NULL); | 420 | class_dev_iter_init(&iter, phy_class, NULL, NULL); |
| 403 | while ((dev = class_dev_iter_next(&iter))) { | 421 | while ((dev = class_dev_iter_next(&iter))) { |
| 404 | phy = to_phy(dev); | 422 | phy = to_phy(dev); |
| 405 | if (node != phy->dev.of_node) | 423 | if (node != phy->dev.of_node) { |
| 424 | for_each_child_of_node(node, child) { | ||
| 425 | if (child == phy->dev.of_node) | ||
| 426 | goto phy_found; | ||
| 427 | } | ||
| 406 | continue; | 428 | continue; |
| 429 | } | ||
| 407 | 430 | ||
| 431 | phy_found: | ||
| 408 | class_dev_iter_exit(&iter); | 432 | class_dev_iter_exit(&iter); |
| 409 | return phy; | 433 | return phy; |
| 410 | } | 434 | } |
| @@ -562,13 +586,15 @@ EXPORT_SYMBOL_GPL(devm_of_phy_get); | |||
| 562 | /** | 586 | /** |
| 563 | * phy_create() - create a new phy | 587 | * phy_create() - create a new phy |
| 564 | * @dev: device that is creating the new phy | 588 | * @dev: device that is creating the new phy |
| 589 | * @node: device node of the phy | ||
| 565 | * @ops: function pointers for performing phy operations | 590 | * @ops: function pointers for performing phy operations |
| 566 | * @init_data: contains the list of PHY consumers or NULL | 591 | * @init_data: contains the list of PHY consumers or NULL |
| 567 | * | 592 | * |
| 568 | * Called to create a phy using phy framework. | 593 | * Called to create a phy using phy framework. |
| 569 | */ | 594 | */ |
| 570 | struct phy *phy_create(struct device *dev, const struct phy_ops *ops, | 595 | struct phy *phy_create(struct device *dev, struct device_node *node, |
| 571 | struct phy_init_data *init_data) | 596 | const struct phy_ops *ops, |
| 597 | struct phy_init_data *init_data) | ||
| 572 | { | 598 | { |
| 573 | int ret; | 599 | int ret; |
| 574 | int id; | 600 | int id; |
| @@ -588,12 +614,22 @@ struct phy *phy_create(struct device *dev, const struct phy_ops *ops, | |||
| 588 | goto free_phy; | 614 | goto free_phy; |
| 589 | } | 615 | } |
| 590 | 616 | ||
| 617 | /* phy-supply */ | ||
| 618 | phy->pwr = regulator_get_optional(dev, "phy"); | ||
| 619 | if (IS_ERR(phy->pwr)) { | ||
| 620 | if (PTR_ERR(phy->pwr) == -EPROBE_DEFER) { | ||
| 621 | ret = -EPROBE_DEFER; | ||
| 622 | goto free_ida; | ||
| 623 | } | ||
| 624 | phy->pwr = NULL; | ||
| 625 | } | ||
| 626 | |||
| 591 | device_initialize(&phy->dev); | 627 | device_initialize(&phy->dev); |
| 592 | mutex_init(&phy->mutex); | 628 | mutex_init(&phy->mutex); |
| 593 | 629 | ||
| 594 | phy->dev.class = phy_class; | 630 | phy->dev.class = phy_class; |
| 595 | phy->dev.parent = dev; | 631 | phy->dev.parent = dev; |
| 596 | phy->dev.of_node = dev->of_node; | 632 | phy->dev.of_node = node ?: dev->of_node; |
| 597 | phy->id = id; | 633 | phy->id = id; |
| 598 | phy->ops = ops; | 634 | phy->ops = ops; |
| 599 | phy->init_data = init_data; | 635 | phy->init_data = init_data; |
| @@ -617,6 +653,9 @@ put_dev: | |||
| 617 | put_device(&phy->dev); /* calls phy_release() which frees resources */ | 653 | put_device(&phy->dev); /* calls phy_release() which frees resources */ |
| 618 | return ERR_PTR(ret); | 654 | return ERR_PTR(ret); |
| 619 | 655 | ||
| 656 | free_ida: | ||
| 657 | ida_simple_remove(&phy_ida, phy->id); | ||
| 658 | |||
| 620 | free_phy: | 659 | free_phy: |
| 621 | kfree(phy); | 660 | kfree(phy); |
| 622 | return ERR_PTR(ret); | 661 | return ERR_PTR(ret); |
| @@ -626,6 +665,7 @@ EXPORT_SYMBOL_GPL(phy_create); | |||
| 626 | /** | 665 | /** |
| 627 | * devm_phy_create() - create a new phy | 666 | * devm_phy_create() - create a new phy |
| 628 | * @dev: device that is creating the new phy | 667 | * @dev: device that is creating the new phy |
| 668 | * @node: device node of the phy | ||
| 629 | * @ops: function pointers for performing phy operations | 669 | * @ops: function pointers for performing phy operations |
| 630 | * @init_data: contains the list of PHY consumers or NULL | 670 | * @init_data: contains the list of PHY consumers or NULL |
| 631 | * | 671 | * |
| @@ -634,8 +674,9 @@ EXPORT_SYMBOL_GPL(phy_create); | |||
| 634 | * On driver detach, release function is invoked on the devres data, | 674 | * On driver detach, release function is invoked on the devres data, |
| 635 | * then, devres data is freed. | 675 | * then, devres data is freed. |
| 636 | */ | 676 | */ |
| 637 | struct phy *devm_phy_create(struct device *dev, const struct phy_ops *ops, | 677 | struct phy *devm_phy_create(struct device *dev, struct device_node *node, |
| 638 | struct phy_init_data *init_data) | 678 | const struct phy_ops *ops, |
| 679 | struct phy_init_data *init_data) | ||
| 639 | { | 680 | { |
| 640 | struct phy **ptr, *phy; | 681 | struct phy **ptr, *phy; |
| 641 | 682 | ||
| @@ -643,7 +684,7 @@ struct phy *devm_phy_create(struct device *dev, const struct phy_ops *ops, | |||
| 643 | if (!ptr) | 684 | if (!ptr) |
| 644 | return ERR_PTR(-ENOMEM); | 685 | return ERR_PTR(-ENOMEM); |
| 645 | 686 | ||
| 646 | phy = phy_create(dev, ops, init_data); | 687 | phy = phy_create(dev, node, ops, init_data); |
| 647 | if (!IS_ERR(phy)) { | 688 | if (!IS_ERR(phy)) { |
| 648 | *ptr = phy; | 689 | *ptr = phy; |
| 649 | devres_add(dev, ptr); | 690 | devres_add(dev, ptr); |
| @@ -800,6 +841,7 @@ static void phy_release(struct device *dev) | |||
| 800 | 841 | ||
| 801 | phy = to_phy(dev); | 842 | phy = to_phy(dev); |
| 802 | dev_vdbg(dev, "releasing '%s'\n", dev_name(dev)); | 843 | dev_vdbg(dev, "releasing '%s'\n", dev_name(dev)); |
| 844 | regulator_put(phy->pwr); | ||
| 803 | ida_simple_remove(&phy_ida, phy->id); | 845 | ida_simple_remove(&phy_ida, phy->id); |
| 804 | kfree(phy); | 846 | kfree(phy); |
| 805 | } | 847 | } |
diff --git a/drivers/phy/phy-exynos-dp-video.c b/drivers/phy/phy-exynos-dp-video.c index 0786fef842e7..8b3026e2af7f 100644 --- a/drivers/phy/phy-exynos-dp-video.c +++ b/drivers/phy/phy-exynos-dp-video.c | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | #include <linux/err.h> | ||
| 12 | #include <linux/io.h> | 13 | #include <linux/io.h> |
| 13 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
| 14 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| @@ -76,7 +77,7 @@ static int exynos_dp_video_phy_probe(struct platform_device *pdev) | |||
| 76 | if (IS_ERR(state->regs)) | 77 | if (IS_ERR(state->regs)) |
| 77 | return PTR_ERR(state->regs); | 78 | return PTR_ERR(state->regs); |
| 78 | 79 | ||
| 79 | phy = devm_phy_create(dev, &exynos_dp_video_phy_ops, NULL); | 80 | phy = devm_phy_create(dev, NULL, &exynos_dp_video_phy_ops, NULL); |
| 80 | if (IS_ERR(phy)) { | 81 | if (IS_ERR(phy)) { |
| 81 | dev_err(dev, "failed to create Display Port PHY\n"); | 82 | dev_err(dev, "failed to create Display Port PHY\n"); |
| 82 | return PTR_ERR(phy); | 83 | return PTR_ERR(phy); |
| @@ -84,10 +85,8 @@ static int exynos_dp_video_phy_probe(struct platform_device *pdev) | |||
| 84 | phy_set_drvdata(phy, state); | 85 | phy_set_drvdata(phy, state); |
| 85 | 86 | ||
| 86 | phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); | 87 | phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); |
| 87 | if (IS_ERR(phy_provider)) | ||
| 88 | return PTR_ERR(phy_provider); | ||
| 89 | 88 | ||
| 90 | return 0; | 89 | return PTR_ERR_OR_ZERO(phy_provider); |
| 91 | } | 90 | } |
| 92 | 91 | ||
| 93 | static const struct of_device_id exynos_dp_video_phy_of_match[] = { | 92 | static const struct of_device_id exynos_dp_video_phy_of_match[] = { |
diff --git a/drivers/phy/phy-exynos-mipi-video.c b/drivers/phy/phy-exynos-mipi-video.c index ff026689358c..b55a92e12496 100644 --- a/drivers/phy/phy-exynos-mipi-video.c +++ b/drivers/phy/phy-exynos-mipi-video.c | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | #include <linux/err.h> | ||
| 12 | #include <linux/io.h> | 13 | #include <linux/io.h> |
| 13 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
| 14 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| @@ -135,7 +136,7 @@ static int exynos_mipi_video_phy_probe(struct platform_device *pdev) | |||
| 135 | spin_lock_init(&state->slock); | 136 | spin_lock_init(&state->slock); |
| 136 | 137 | ||
| 137 | for (i = 0; i < EXYNOS_MIPI_PHYS_NUM; i++) { | 138 | for (i = 0; i < EXYNOS_MIPI_PHYS_NUM; i++) { |
| 138 | struct phy *phy = devm_phy_create(dev, | 139 | struct phy *phy = devm_phy_create(dev, NULL, |
| 139 | &exynos_mipi_video_phy_ops, NULL); | 140 | &exynos_mipi_video_phy_ops, NULL); |
| 140 | if (IS_ERR(phy)) { | 141 | if (IS_ERR(phy)) { |
| 141 | dev_err(dev, "failed to create PHY %d\n", i); | 142 | dev_err(dev, "failed to create PHY %d\n", i); |
| @@ -149,10 +150,8 @@ static int exynos_mipi_video_phy_probe(struct platform_device *pdev) | |||
| 149 | 150 | ||
| 150 | phy_provider = devm_of_phy_provider_register(dev, | 151 | phy_provider = devm_of_phy_provider_register(dev, |
| 151 | exynos_mipi_video_phy_xlate); | 152 | exynos_mipi_video_phy_xlate); |
| 152 | if (IS_ERR(phy_provider)) | ||
| 153 | return PTR_ERR(phy_provider); | ||
| 154 | 153 | ||
| 155 | return 0; | 154 | return PTR_ERR_OR_ZERO(phy_provider); |
| 156 | } | 155 | } |
| 157 | 156 | ||
| 158 | static const struct of_device_id exynos_mipi_video_phy_of_match[] = { | 157 | static const struct of_device_id exynos_mipi_video_phy_of_match[] = { |
diff --git a/drivers/phy/phy-exynos4x12-usb2.c b/drivers/phy/phy-exynos4x12-usb2.c index d92a7cc5698a..0b9de88579b1 100644 --- a/drivers/phy/phy-exynos4x12-usb2.c +++ b/drivers/phy/phy-exynos4x12-usb2.c | |||
| @@ -67,6 +67,8 @@ | |||
| 67 | #define EXYNOS_4x12_UPHYCLK_PHYFSEL_24MHZ (0x5 << 0) | 67 | #define EXYNOS_4x12_UPHYCLK_PHYFSEL_24MHZ (0x5 << 0) |
| 68 | #define EXYNOS_4x12_UPHYCLK_PHYFSEL_50MHZ (0x7 << 0) | 68 | #define EXYNOS_4x12_UPHYCLK_PHYFSEL_50MHZ (0x7 << 0) |
| 69 | 69 | ||
| 70 | #define EXYNOS_3250_UPHYCLK_REFCLKSEL (0x2 << 8) | ||
| 71 | |||
| 70 | #define EXYNOS_4x12_UPHYCLK_PHY0_ID_PULLUP BIT(3) | 72 | #define EXYNOS_4x12_UPHYCLK_PHY0_ID_PULLUP BIT(3) |
| 71 | #define EXYNOS_4x12_UPHYCLK_PHY0_COMMON_ON BIT(4) | 73 | #define EXYNOS_4x12_UPHYCLK_PHY0_COMMON_ON BIT(4) |
| 72 | #define EXYNOS_4x12_UPHYCLK_PHY1_COMMON_ON BIT(7) | 74 | #define EXYNOS_4x12_UPHYCLK_PHY1_COMMON_ON BIT(7) |
| @@ -86,13 +88,23 @@ | |||
| 86 | #define EXYNOS_4x12_URSTCON_OTG_HLINK BIT(1) | 88 | #define EXYNOS_4x12_URSTCON_OTG_HLINK BIT(1) |
| 87 | #define EXYNOS_4x12_URSTCON_OTG_PHYLINK BIT(2) | 89 | #define EXYNOS_4x12_URSTCON_OTG_PHYLINK BIT(2) |
| 88 | #define EXYNOS_4x12_URSTCON_HOST_PHY BIT(3) | 90 | #define EXYNOS_4x12_URSTCON_HOST_PHY BIT(3) |
| 91 | /* The following bit defines are presented in the | ||
| 92 | * order taken from the Exynos4412 reference manual. | ||
| 93 | * | ||
| 94 | * During experiments with the hardware and debugging | ||
| 95 | * it was determined that the hardware behaves contrary | ||
| 96 | * to the manual. | ||
| 97 | * | ||
| 98 | * The following bit values were chaned accordingly to the | ||
| 99 | * results of real hardware experiments. | ||
| 100 | */ | ||
| 89 | #define EXYNOS_4x12_URSTCON_PHY1 BIT(4) | 101 | #define EXYNOS_4x12_URSTCON_PHY1 BIT(4) |
| 90 | #define EXYNOS_4x12_URSTCON_HSIC0 BIT(5) | 102 | #define EXYNOS_4x12_URSTCON_HSIC0 BIT(6) |
| 91 | #define EXYNOS_4x12_URSTCON_HSIC1 BIT(6) | 103 | #define EXYNOS_4x12_URSTCON_HSIC1 BIT(5) |
| 92 | #define EXYNOS_4x12_URSTCON_HOST_LINK_ALL BIT(7) | 104 | #define EXYNOS_4x12_URSTCON_HOST_LINK_ALL BIT(7) |
| 93 | #define EXYNOS_4x12_URSTCON_HOST_LINK_P0 BIT(8) | 105 | #define EXYNOS_4x12_URSTCON_HOST_LINK_P0 BIT(10) |
| 94 | #define EXYNOS_4x12_URSTCON_HOST_LINK_P1 BIT(9) | 106 | #define EXYNOS_4x12_URSTCON_HOST_LINK_P1 BIT(9) |
| 95 | #define EXYNOS_4x12_URSTCON_HOST_LINK_P2 BIT(10) | 107 | #define EXYNOS_4x12_URSTCON_HOST_LINK_P2 BIT(8) |
| 96 | 108 | ||
| 97 | /* Isolation, configured in the power management unit */ | 109 | /* Isolation, configured in the power management unit */ |
| 98 | #define EXYNOS_4x12_USB_ISOL_OFFSET 0x704 | 110 | #define EXYNOS_4x12_USB_ISOL_OFFSET 0x704 |
| @@ -187,7 +199,12 @@ static void exynos4x12_setup_clk(struct samsung_usb2_phy_instance *inst) | |||
| 187 | 199 | ||
| 188 | clk = readl(drv->reg_phy + EXYNOS_4x12_UPHYCLK); | 200 | clk = readl(drv->reg_phy + EXYNOS_4x12_UPHYCLK); |
| 189 | clk &= ~EXYNOS_4x12_UPHYCLK_PHYFSEL_MASK; | 201 | clk &= ~EXYNOS_4x12_UPHYCLK_PHYFSEL_MASK; |
| 202 | |||
| 203 | if (drv->cfg->has_refclk_sel) | ||
| 204 | clk = EXYNOS_3250_UPHYCLK_REFCLKSEL; | ||
| 205 | |||
| 190 | clk |= drv->ref_reg_val << EXYNOS_4x12_UPHYCLK_PHYFSEL_OFFSET; | 206 | clk |= drv->ref_reg_val << EXYNOS_4x12_UPHYCLK_PHYFSEL_OFFSET; |
| 207 | clk |= EXYNOS_4x12_UPHYCLK_PHY1_COMMON_ON; | ||
| 191 | writel(clk, drv->reg_phy + EXYNOS_4x12_UPHYCLK); | 208 | writel(clk, drv->reg_phy + EXYNOS_4x12_UPHYCLK); |
| 192 | } | 209 | } |
| 193 | 210 | ||
| @@ -198,27 +215,22 @@ static void exynos4x12_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on) | |||
| 198 | u32 phypwr = 0; | 215 | u32 phypwr = 0; |
| 199 | u32 rst; | 216 | u32 rst; |
| 200 | u32 pwr; | 217 | u32 pwr; |
| 201 | u32 mode = 0; | ||
| 202 | u32 switch_mode = 0; | ||
| 203 | 218 | ||
| 204 | switch (inst->cfg->id) { | 219 | switch (inst->cfg->id) { |
| 205 | case EXYNOS4x12_DEVICE: | 220 | case EXYNOS4x12_DEVICE: |
| 206 | phypwr = EXYNOS_4x12_UPHYPWR_PHY0; | 221 | phypwr = EXYNOS_4x12_UPHYPWR_PHY0; |
| 207 | rstbits = EXYNOS_4x12_URSTCON_PHY0; | 222 | rstbits = EXYNOS_4x12_URSTCON_PHY0; |
| 208 | mode = EXYNOS_4x12_MODE_SWITCH_DEVICE; | ||
| 209 | switch_mode = 1; | ||
| 210 | break; | 223 | break; |
| 211 | case EXYNOS4x12_HOST: | 224 | case EXYNOS4x12_HOST: |
| 212 | phypwr = EXYNOS_4x12_UPHYPWR_PHY1; | 225 | phypwr = EXYNOS_4x12_UPHYPWR_PHY1; |
| 213 | rstbits = EXYNOS_4x12_URSTCON_HOST_PHY; | 226 | rstbits = EXYNOS_4x12_URSTCON_HOST_PHY | |
| 214 | mode = EXYNOS_4x12_MODE_SWITCH_HOST; | 227 | EXYNOS_4x12_URSTCON_PHY1 | |
| 215 | switch_mode = 1; | 228 | EXYNOS_4x12_URSTCON_HOST_LINK_P0; |
| 216 | break; | 229 | break; |
| 217 | case EXYNOS4x12_HSIC0: | 230 | case EXYNOS4x12_HSIC0: |
| 218 | phypwr = EXYNOS_4x12_UPHYPWR_HSIC0; | 231 | phypwr = EXYNOS_4x12_UPHYPWR_HSIC0; |
| 219 | rstbits = EXYNOS_4x12_URSTCON_HSIC1 | | 232 | rstbits = EXYNOS_4x12_URSTCON_HSIC0 | |
| 220 | EXYNOS_4x12_URSTCON_HOST_LINK_P0 | | 233 | EXYNOS_4x12_URSTCON_HOST_LINK_P1; |
| 221 | EXYNOS_4x12_URSTCON_HOST_PHY; | ||
| 222 | break; | 234 | break; |
| 223 | case EXYNOS4x12_HSIC1: | 235 | case EXYNOS4x12_HSIC1: |
| 224 | phypwr = EXYNOS_4x12_UPHYPWR_HSIC1; | 236 | phypwr = EXYNOS_4x12_UPHYPWR_HSIC1; |
| @@ -228,11 +240,6 @@ static void exynos4x12_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on) | |||
| 228 | }; | 240 | }; |
| 229 | 241 | ||
| 230 | if (on) { | 242 | if (on) { |
| 231 | if (switch_mode) | ||
| 232 | regmap_update_bits(drv->reg_sys, | ||
| 233 | EXYNOS_4x12_MODE_SWITCH_OFFSET, | ||
| 234 | EXYNOS_4x12_MODE_SWITCH_MASK, mode); | ||
| 235 | |||
| 236 | pwr = readl(drv->reg_phy + EXYNOS_4x12_UPHYPWR); | 243 | pwr = readl(drv->reg_phy + EXYNOS_4x12_UPHYPWR); |
| 237 | pwr &= ~phypwr; | 244 | pwr &= ~phypwr; |
| 238 | writel(pwr, drv->reg_phy + EXYNOS_4x12_UPHYPWR); | 245 | writel(pwr, drv->reg_phy + EXYNOS_4x12_UPHYPWR); |
| @@ -253,41 +260,78 @@ static void exynos4x12_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on) | |||
| 253 | } | 260 | } |
| 254 | } | 261 | } |
| 255 | 262 | ||
| 256 | static int exynos4x12_power_on(struct samsung_usb2_phy_instance *inst) | 263 | static void exynos4x12_power_on_int(struct samsung_usb2_phy_instance *inst) |
| 257 | { | 264 | { |
| 258 | struct samsung_usb2_phy_driver *drv = inst->drv; | 265 | if (inst->int_cnt++ > 0) |
| 266 | return; | ||
| 259 | 267 | ||
| 260 | inst->enabled = 1; | ||
| 261 | exynos4x12_setup_clk(inst); | 268 | exynos4x12_setup_clk(inst); |
| 262 | exynos4x12_phy_pwr(inst, 1); | ||
| 263 | exynos4x12_isol(inst, 0); | 269 | exynos4x12_isol(inst, 0); |
| 270 | exynos4x12_phy_pwr(inst, 1); | ||
| 271 | } | ||
| 272 | |||
| 273 | static int exynos4x12_power_on(struct samsung_usb2_phy_instance *inst) | ||
| 274 | { | ||
| 275 | struct samsung_usb2_phy_driver *drv = inst->drv; | ||
| 276 | |||
| 277 | if (inst->ext_cnt++ > 0) | ||
| 278 | return 0; | ||
| 264 | 279 | ||
| 265 | /* Power on the device, as it is necessary for HSIC to work */ | 280 | if (inst->cfg->id == EXYNOS4x12_HOST) { |
| 266 | if (inst->cfg->id == EXYNOS4x12_HSIC0) { | 281 | regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET, |
| 267 | struct samsung_usb2_phy_instance *device = | 282 | EXYNOS_4x12_MODE_SWITCH_MASK, |
| 268 | &drv->instances[EXYNOS4x12_DEVICE]; | 283 | EXYNOS_4x12_MODE_SWITCH_HOST); |
| 269 | exynos4x12_phy_pwr(device, 1); | 284 | exynos4x12_power_on_int(&drv->instances[EXYNOS4x12_DEVICE]); |
| 270 | exynos4x12_isol(device, 0); | ||
| 271 | } | 285 | } |
| 272 | 286 | ||
| 287 | if (inst->cfg->id == EXYNOS4x12_DEVICE && drv->cfg->has_mode_switch) | ||
| 288 | regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET, | ||
| 289 | EXYNOS_4x12_MODE_SWITCH_MASK, | ||
| 290 | EXYNOS_4x12_MODE_SWITCH_DEVICE); | ||
| 291 | |||
| 292 | if (inst->cfg->id == EXYNOS4x12_HSIC0 || | ||
| 293 | inst->cfg->id == EXYNOS4x12_HSIC1) { | ||
| 294 | exynos4x12_power_on_int(&drv->instances[EXYNOS4x12_DEVICE]); | ||
| 295 | exynos4x12_power_on_int(&drv->instances[EXYNOS4x12_HOST]); | ||
| 296 | } | ||
| 297 | |||
| 298 | exynos4x12_power_on_int(inst); | ||
| 299 | |||
| 273 | return 0; | 300 | return 0; |
| 274 | } | 301 | } |
| 275 | 302 | ||
| 276 | static int exynos4x12_power_off(struct samsung_usb2_phy_instance *inst) | 303 | static void exynos4x12_power_off_int(struct samsung_usb2_phy_instance *inst) |
| 277 | { | 304 | { |
| 278 | struct samsung_usb2_phy_driver *drv = inst->drv; | 305 | if (inst->int_cnt-- > 1) |
| 279 | struct samsung_usb2_phy_instance *device = | 306 | return; |
| 280 | &drv->instances[EXYNOS4x12_DEVICE]; | ||
| 281 | 307 | ||
| 282 | inst->enabled = 0; | ||
| 283 | exynos4x12_isol(inst, 1); | 308 | exynos4x12_isol(inst, 1); |
| 284 | exynos4x12_phy_pwr(inst, 0); | 309 | exynos4x12_phy_pwr(inst, 0); |
| 310 | } | ||
| 311 | |||
| 312 | static int exynos4x12_power_off(struct samsung_usb2_phy_instance *inst) | ||
| 313 | { | ||
| 314 | struct samsung_usb2_phy_driver *drv = inst->drv; | ||
| 315 | |||
| 316 | if (inst->ext_cnt-- > 1) | ||
| 317 | return 0; | ||
| 318 | |||
| 319 | if (inst->cfg->id == EXYNOS4x12_DEVICE && drv->cfg->has_mode_switch) | ||
| 320 | regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET, | ||
| 321 | EXYNOS_4x12_MODE_SWITCH_MASK, | ||
| 322 | EXYNOS_4x12_MODE_SWITCH_HOST); | ||
| 323 | |||
| 324 | if (inst->cfg->id == EXYNOS4x12_HOST) | ||
| 325 | exynos4x12_power_off_int(&drv->instances[EXYNOS4x12_DEVICE]); | ||
| 285 | 326 | ||
| 286 | if (inst->cfg->id == EXYNOS4x12_HSIC0 && !device->enabled) { | 327 | if (inst->cfg->id == EXYNOS4x12_HSIC0 || |
| 287 | exynos4x12_isol(device, 1); | 328 | inst->cfg->id == EXYNOS4x12_HSIC1) { |
| 288 | exynos4x12_phy_pwr(device, 0); | 329 | exynos4x12_power_off_int(&drv->instances[EXYNOS4x12_DEVICE]); |
| 330 | exynos4x12_power_off_int(&drv->instances[EXYNOS4x12_HOST]); | ||
| 289 | } | 331 | } |
| 290 | 332 | ||
| 333 | exynos4x12_power_off_int(inst); | ||
| 334 | |||
| 291 | return 0; | 335 | return 0; |
| 292 | } | 336 | } |
| 293 | 337 | ||
| @@ -320,6 +364,13 @@ static const struct samsung_usb2_common_phy exynos4x12_phys[] = { | |||
| 320 | {}, | 364 | {}, |
| 321 | }; | 365 | }; |
| 322 | 366 | ||
| 367 | const struct samsung_usb2_phy_config exynos3250_usb2_phy_config = { | ||
| 368 | .has_refclk_sel = 1, | ||
| 369 | .num_phys = 1, | ||
| 370 | .phys = exynos4x12_phys, | ||
| 371 | .rate_to_clk = exynos4x12_rate_to_clk, | ||
| 372 | }; | ||
| 373 | |||
| 323 | const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config = { | 374 | const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config = { |
| 324 | .has_mode_switch = 1, | 375 | .has_mode_switch = 1, |
| 325 | .num_phys = EXYNOS4x12_NUM_PHYS, | 376 | .num_phys = EXYNOS4x12_NUM_PHYS, |
diff --git a/drivers/phy/phy-exynos5-usbdrd.c b/drivers/phy/phy-exynos5-usbdrd.c index 76d862b2202f..b05302b09c9f 100644 --- a/drivers/phy/phy-exynos5-usbdrd.c +++ b/drivers/phy/phy-exynos5-usbdrd.c | |||
| @@ -506,7 +506,7 @@ static struct phy_ops exynos5_usbdrd_phy_ops = { | |||
| 506 | .owner = THIS_MODULE, | 506 | .owner = THIS_MODULE, |
| 507 | }; | 507 | }; |
| 508 | 508 | ||
| 509 | const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = { | 509 | static const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = { |
| 510 | { | 510 | { |
| 511 | .id = EXYNOS5_DRDPHY_UTMI, | 511 | .id = EXYNOS5_DRDPHY_UTMI, |
| 512 | .phy_isol = exynos5_usbdrd_phy_isol, | 512 | .phy_isol = exynos5_usbdrd_phy_isol, |
| @@ -521,13 +521,13 @@ const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = { | |||
| 521 | }, | 521 | }, |
| 522 | }; | 522 | }; |
| 523 | 523 | ||
| 524 | const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = { | 524 | static const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = { |
| 525 | .phy_cfg = phy_cfg_exynos5, | 525 | .phy_cfg = phy_cfg_exynos5, |
| 526 | .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL, | 526 | .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL, |
| 527 | .pmu_offset_usbdrd1_phy = EXYNOS5420_USBDRD1_PHY_CONTROL, | 527 | .pmu_offset_usbdrd1_phy = EXYNOS5420_USBDRD1_PHY_CONTROL, |
| 528 | }; | 528 | }; |
| 529 | 529 | ||
| 530 | const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = { | 530 | static const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = { |
| 531 | .phy_cfg = phy_cfg_exynos5, | 531 | .phy_cfg = phy_cfg_exynos5, |
| 532 | .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL, | 532 | .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL, |
| 533 | }; | 533 | }; |
| @@ -635,7 +635,8 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev) | |||
| 635 | dev_vdbg(dev, "Creating usbdrd_phy phy\n"); | 635 | dev_vdbg(dev, "Creating usbdrd_phy phy\n"); |
| 636 | 636 | ||
| 637 | for (i = 0; i < EXYNOS5_DRDPHYS_NUM; i++) { | 637 | for (i = 0; i < EXYNOS5_DRDPHYS_NUM; i++) { |
| 638 | struct phy *phy = devm_phy_create(dev, &exynos5_usbdrd_phy_ops, | 638 | struct phy *phy = devm_phy_create(dev, NULL, |
| 639 | &exynos5_usbdrd_phy_ops, | ||
| 639 | NULL); | 640 | NULL); |
| 640 | if (IS_ERR(phy)) { | 641 | if (IS_ERR(phy)) { |
| 641 | dev_err(dev, "Failed to create usbdrd_phy phy\n"); | 642 | dev_err(dev, "Failed to create usbdrd_phy phy\n"); |
diff --git a/drivers/phy/phy-exynos5250-sata.c b/drivers/phy/phy-exynos5250-sata.c index 05689450f93b..19a679aca4ac 100644 --- a/drivers/phy/phy-exynos5250-sata.c +++ b/drivers/phy/phy-exynos5250-sata.c | |||
| @@ -210,7 +210,7 @@ static int exynos_sata_phy_probe(struct platform_device *pdev) | |||
| 210 | return ret; | 210 | return ret; |
| 211 | } | 211 | } |
| 212 | 212 | ||
| 213 | sata_phy->phy = devm_phy_create(dev, &exynos_sata_phy_ops, NULL); | 213 | sata_phy->phy = devm_phy_create(dev, NULL, &exynos_sata_phy_ops, NULL); |
| 214 | if (IS_ERR(sata_phy->phy)) { | 214 | if (IS_ERR(sata_phy->phy)) { |
| 215 | clk_disable_unprepare(sata_phy->phyclk); | 215 | clk_disable_unprepare(sata_phy->phyclk); |
| 216 | dev_err(dev, "failed to create PHY\n"); | 216 | dev_err(dev, "failed to create PHY\n"); |
diff --git a/drivers/phy/phy-exynos5250-usb2.c b/drivers/phy/phy-exynos5250-usb2.c index 94179afda951..1c139aa0d074 100644 --- a/drivers/phy/phy-exynos5250-usb2.c +++ b/drivers/phy/phy-exynos5250-usb2.c | |||
| @@ -318,7 +318,6 @@ static int exynos5250_power_on(struct samsung_usb2_phy_instance *inst) | |||
| 318 | 318 | ||
| 319 | break; | 319 | break; |
| 320 | } | 320 | } |
| 321 | inst->enabled = 1; | ||
| 322 | exynos5250_isol(inst, 0); | 321 | exynos5250_isol(inst, 0); |
| 323 | 322 | ||
| 324 | return 0; | 323 | return 0; |
| @@ -331,7 +330,6 @@ static int exynos5250_power_off(struct samsung_usb2_phy_instance *inst) | |||
| 331 | u32 otg; | 330 | u32 otg; |
| 332 | u32 hsic; | 331 | u32 hsic; |
| 333 | 332 | ||
| 334 | inst->enabled = 0; | ||
| 335 | exynos5250_isol(inst, 1); | 333 | exynos5250_isol(inst, 1); |
| 336 | 334 | ||
| 337 | switch (inst->cfg->id) { | 335 | switch (inst->cfg->id) { |
diff --git a/drivers/phy/phy-hix5hd2-sata.c b/drivers/phy/phy-hix5hd2-sata.c new file mode 100644 index 000000000000..6a08fa5f81eb --- /dev/null +++ b/drivers/phy/phy-hix5hd2-sata.c | |||
| @@ -0,0 +1,192 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2014 Linaro Ltd. | ||
| 3 | * Copyright (c) 2014 Hisilicon Limited. | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License as published by | ||
| 7 | * the Free Software Foundation; either version 2 of the License, or | ||
| 8 | * (at your option) any later version. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/delay.h> | ||
| 12 | #include <linux/io.h> | ||
| 13 | #include <linux/mfd/syscon.h> | ||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/phy/phy.h> | ||
| 16 | #include <linux/platform_device.h> | ||
| 17 | #include <linux/regmap.h> | ||
| 18 | |||
| 19 | #define SATA_PHY0_CTLL 0xa0 | ||
| 20 | #define MPLL_MULTIPLIER_SHIFT 1 | ||
| 21 | #define MPLL_MULTIPLIER_MASK 0xfe | ||
| 22 | #define MPLL_MULTIPLIER_50M 0x3c | ||
| 23 | #define MPLL_MULTIPLIER_100M 0x1e | ||
| 24 | #define PHY_RESET BIT(0) | ||
| 25 | #define REF_SSP_EN BIT(9) | ||
| 26 | #define SSC_EN BIT(10) | ||
| 27 | #define REF_USE_PAD BIT(23) | ||
| 28 | |||
| 29 | #define SATA_PORT_PHYCTL 0x174 | ||
| 30 | #define SPEED_MODE_MASK 0x6f0000 | ||
| 31 | #define HALF_RATE_SHIFT 16 | ||
| 32 | #define PHY_CONFIG_SHIFT 18 | ||
| 33 | #define GEN2_EN_SHIFT 21 | ||
| 34 | #define SPEED_CTRL BIT(20) | ||
| 35 | |||
| 36 | #define SATA_PORT_PHYCTL1 0x148 | ||
| 37 | #define AMPLITUDE_MASK 0x3ffffe | ||
| 38 | #define AMPLITUDE_GEN3 0x68 | ||
| 39 | #define AMPLITUDE_GEN3_SHIFT 15 | ||
| 40 | #define AMPLITUDE_GEN2 0x56 | ||
| 41 | #define AMPLITUDE_GEN2_SHIFT 8 | ||
| 42 | #define AMPLITUDE_GEN1 0x56 | ||
| 43 | #define AMPLITUDE_GEN1_SHIFT 1 | ||
| 44 | |||
| 45 | #define SATA_PORT_PHYCTL2 0x14c | ||
| 46 | #define PREEMPH_MASK 0x3ffff | ||
| 47 | #define PREEMPH_GEN3 0x20 | ||
| 48 | #define PREEMPH_GEN3_SHIFT 12 | ||
| 49 | #define PREEMPH_GEN2 0x15 | ||
| 50 | #define PREEMPH_GEN2_SHIFT 6 | ||
| 51 | #define PREEMPH_GEN1 0x5 | ||
| 52 | #define PREEMPH_GEN1_SHIFT 0 | ||
| 53 | |||
| 54 | struct hix5hd2_priv { | ||
| 55 | void __iomem *base; | ||
| 56 | struct regmap *peri_ctrl; | ||
| 57 | }; | ||
| 58 | |||
| 59 | enum phy_speed_mode { | ||
| 60 | SPEED_MODE_GEN1 = 0, | ||
| 61 | SPEED_MODE_GEN2 = 1, | ||
| 62 | SPEED_MODE_GEN3 = 2, | ||
| 63 | }; | ||
| 64 | |||
| 65 | static int hix5hd2_sata_phy_init(struct phy *phy) | ||
| 66 | { | ||
| 67 | struct hix5hd2_priv *priv = phy_get_drvdata(phy); | ||
| 68 | u32 val, data[2]; | ||
| 69 | int ret; | ||
| 70 | |||
| 71 | if (priv->peri_ctrl) { | ||
| 72 | ret = of_property_read_u32_array(phy->dev.of_node, | ||
| 73 | "hisilicon,power-reg", | ||
| 74 | &data[0], 2); | ||
| 75 | if (ret) { | ||
| 76 | dev_err(&phy->dev, "Fail read hisilicon,power-reg\n"); | ||
| 77 | return ret; | ||
| 78 | } | ||
| 79 | |||
| 80 | regmap_update_bits(priv->peri_ctrl, data[0], | ||
| 81 | BIT(data[1]), BIT(data[1])); | ||
| 82 | } | ||
| 83 | |||
| 84 | /* reset phy */ | ||
| 85 | val = readl_relaxed(priv->base + SATA_PHY0_CTLL); | ||
| 86 | val &= ~(MPLL_MULTIPLIER_MASK | REF_USE_PAD); | ||
| 87 | val |= MPLL_MULTIPLIER_50M << MPLL_MULTIPLIER_SHIFT | | ||
| 88 | REF_SSP_EN | PHY_RESET; | ||
| 89 | writel_relaxed(val, priv->base + SATA_PHY0_CTLL); | ||
| 90 | msleep(20); | ||
| 91 | val &= ~PHY_RESET; | ||
| 92 | writel_relaxed(val, priv->base + SATA_PHY0_CTLL); | ||
| 93 | |||
| 94 | val = readl_relaxed(priv->base + SATA_PORT_PHYCTL1); | ||
| 95 | val &= ~AMPLITUDE_MASK; | ||
| 96 | val |= AMPLITUDE_GEN3 << AMPLITUDE_GEN3_SHIFT | | ||
| 97 | AMPLITUDE_GEN2 << AMPLITUDE_GEN2_SHIFT | | ||
| 98 | AMPLITUDE_GEN1 << AMPLITUDE_GEN1_SHIFT; | ||
| 99 | writel_relaxed(val, priv->base + SATA_PORT_PHYCTL1); | ||
| 100 | |||
| 101 | val = readl_relaxed(priv->base + SATA_PORT_PHYCTL2); | ||
| 102 | val &= ~PREEMPH_MASK; | ||
| 103 | val |= PREEMPH_GEN3 << PREEMPH_GEN3_SHIFT | | ||
| 104 | PREEMPH_GEN2 << PREEMPH_GEN2_SHIFT | | ||
| 105 | PREEMPH_GEN1 << PREEMPH_GEN1_SHIFT; | ||
| 106 | writel_relaxed(val, priv->base + SATA_PORT_PHYCTL2); | ||
| 107 | |||
| 108 | /* ensure PHYCTRL setting takes effect */ | ||
| 109 | val = readl_relaxed(priv->base + SATA_PORT_PHYCTL); | ||
| 110 | val &= ~SPEED_MODE_MASK; | ||
| 111 | val |= SPEED_MODE_GEN1 << HALF_RATE_SHIFT | | ||
| 112 | SPEED_MODE_GEN1 << PHY_CONFIG_SHIFT | | ||
| 113 | SPEED_MODE_GEN1 << GEN2_EN_SHIFT | SPEED_CTRL; | ||
| 114 | writel_relaxed(val, priv->base + SATA_PORT_PHYCTL); | ||
| 115 | |||
| 116 | msleep(20); | ||
| 117 | val &= ~SPEED_MODE_MASK; | ||
| 118 | val |= SPEED_MODE_GEN3 << HALF_RATE_SHIFT | | ||
| 119 | SPEED_MODE_GEN3 << PHY_CONFIG_SHIFT | | ||
| 120 | SPEED_MODE_GEN3 << GEN2_EN_SHIFT | SPEED_CTRL; | ||
| 121 | writel_relaxed(val, priv->base + SATA_PORT_PHYCTL); | ||
| 122 | |||
| 123 | val &= ~(SPEED_MODE_MASK | SPEED_CTRL); | ||
| 124 | val |= SPEED_MODE_GEN2 << HALF_RATE_SHIFT | | ||
| 125 | SPEED_MODE_GEN2 << PHY_CONFIG_SHIFT | | ||
| 126 | SPEED_MODE_GEN2 << GEN2_EN_SHIFT; | ||
| 127 | writel_relaxed(val, priv->base + SATA_PORT_PHYCTL); | ||
| 128 | |||
| 129 | return 0; | ||
| 130 | } | ||
| 131 | |||
| 132 | static struct phy_ops hix5hd2_sata_phy_ops = { | ||
| 133 | .init = hix5hd2_sata_phy_init, | ||
| 134 | .owner = THIS_MODULE, | ||
| 135 | }; | ||
| 136 | |||
| 137 | static int hix5hd2_sata_phy_probe(struct platform_device *pdev) | ||
| 138 | { | ||
| 139 | struct phy_provider *phy_provider; | ||
| 140 | struct device *dev = &pdev->dev; | ||
| 141 | struct resource *res; | ||
| 142 | struct phy *phy; | ||
| 143 | struct hix5hd2_priv *priv; | ||
| 144 | |||
| 145 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | ||
| 146 | if (!priv) | ||
| 147 | return -ENOMEM; | ||
| 148 | |||
| 149 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 150 | priv->base = devm_ioremap(dev, res->start, resource_size(res)); | ||
| 151 | if (!priv->base) | ||
| 152 | return -ENOMEM; | ||
| 153 | |||
| 154 | priv->peri_ctrl = syscon_regmap_lookup_by_phandle(dev->of_node, | ||
| 155 | "hisilicon,peripheral-syscon"); | ||
| 156 | if (IS_ERR(priv->peri_ctrl)) | ||
| 157 | priv->peri_ctrl = NULL; | ||
| 158 | |||
| 159 | phy = devm_phy_create(dev, NULL, &hix5hd2_sata_phy_ops, NULL); | ||
| 160 | if (IS_ERR(phy)) { | ||
| 161 | dev_err(dev, "failed to create PHY\n"); | ||
| 162 | return PTR_ERR(phy); | ||
| 163 | } | ||
| 164 | |||
| 165 | phy_set_drvdata(phy, priv); | ||
| 166 | phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); | ||
| 167 | if (IS_ERR(phy_provider)) | ||
| 168 | return PTR_ERR(phy_provider); | ||
| 169 | |||
| 170 | return 0; | ||
| 171 | } | ||
| 172 | |||
| 173 | static const struct of_device_id hix5hd2_sata_phy_of_match[] = { | ||
| 174 | {.compatible = "hisilicon,hix5hd2-sata-phy",}, | ||
| 175 | { }, | ||
| 176 | }; | ||
| 177 | MODULE_DEVICE_TABLE(of, hix5hd2_sata_phy_of_match); | ||
| 178 | |||
| 179 | static struct platform_driver hix5hd2_sata_phy_driver = { | ||
| 180 | .probe = hix5hd2_sata_phy_probe, | ||
| 181 | .driver = { | ||
| 182 | .name = "hix5hd2-sata-phy", | ||
| 183 | .owner = THIS_MODULE, | ||
| 184 | .of_match_table = hix5hd2_sata_phy_of_match, | ||
| 185 | } | ||
| 186 | }; | ||
| 187 | module_platform_driver(hix5hd2_sata_phy_driver); | ||
| 188 | |||
| 189 | MODULE_AUTHOR("Jiancheng Xue <xuejiancheng@huawei.com>"); | ||
| 190 | MODULE_DESCRIPTION("HISILICON HIX5HD2 SATA PHY driver"); | ||
| 191 | MODULE_ALIAS("platform:hix5hd2-sata-phy"); | ||
| 192 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/phy/phy-miphy365x.c b/drivers/phy/phy-miphy365x.c new file mode 100644 index 000000000000..e111baf187ce --- /dev/null +++ b/drivers/phy/phy-miphy365x.c | |||
| @@ -0,0 +1,636 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2014 STMicroelectronics – All Rights Reserved | ||
| 3 | * | ||
| 4 | * STMicroelectronics PHY driver MiPHY365 (for SoC STiH416). | ||
| 5 | * | ||
| 6 | * Authors: Alexandre Torgue <alexandre.torgue@st.com> | ||
| 7 | * Lee Jones <lee.jones@linaro.org> | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License version 2, as | ||
| 11 | * published by the Free Software Foundation. | ||
| 12 | * | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/platform_device.h> | ||
| 16 | #include <linux/io.h> | ||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include <linux/module.h> | ||
| 19 | #include <linux/of.h> | ||
| 20 | #include <linux/of_platform.h> | ||
| 21 | #include <linux/of_address.h> | ||
| 22 | #include <linux/clk.h> | ||
| 23 | #include <linux/phy/phy.h> | ||
| 24 | #include <linux/delay.h> | ||
| 25 | #include <linux/mfd/syscon.h> | ||
| 26 | #include <linux/regmap.h> | ||
| 27 | |||
| 28 | #include <dt-bindings/phy/phy-miphy365x.h> | ||
| 29 | |||
| 30 | #define HFC_TIMEOUT 100 | ||
| 31 | |||
| 32 | #define SYSCFG_SELECT_SATA_MASK BIT(1) | ||
| 33 | #define SYSCFG_SELECT_SATA_POS 1 | ||
| 34 | |||
| 35 | /* MiPHY365x register definitions */ | ||
| 36 | #define RESET_REG 0x00 | ||
| 37 | #define RST_PLL BIT(1) | ||
| 38 | #define RST_PLL_CAL BIT(2) | ||
| 39 | #define RST_RX BIT(4) | ||
| 40 | #define RST_MACRO BIT(7) | ||
| 41 | |||
| 42 | #define STATUS_REG 0x01 | ||
| 43 | #define IDLL_RDY BIT(0) | ||
| 44 | #define PLL_RDY BIT(1) | ||
| 45 | #define DES_BIT_LOCK BIT(2) | ||
| 46 | #define DES_SYMBOL_LOCK BIT(3) | ||
| 47 | |||
| 48 | #define CTRL_REG 0x02 | ||
| 49 | #define TERM_EN BIT(0) | ||
| 50 | #define PCI_EN BIT(2) | ||
| 51 | #define DES_BIT_LOCK_EN BIT(3) | ||
| 52 | #define TX_POL BIT(5) | ||
| 53 | |||
| 54 | #define INT_CTRL_REG 0x03 | ||
| 55 | |||
| 56 | #define BOUNDARY1_REG 0x10 | ||
| 57 | #define SPDSEL_SEL BIT(0) | ||
| 58 | |||
| 59 | #define BOUNDARY3_REG 0x12 | ||
| 60 | #define TX_SPDSEL_GEN1_VAL 0 | ||
| 61 | #define TX_SPDSEL_GEN2_VAL 0x01 | ||
| 62 | #define TX_SPDSEL_GEN3_VAL 0x02 | ||
| 63 | #define RX_SPDSEL_GEN1_VAL 0 | ||
| 64 | #define RX_SPDSEL_GEN2_VAL (0x01 << 3) | ||
| 65 | #define RX_SPDSEL_GEN3_VAL (0x02 << 3) | ||
| 66 | |||
| 67 | #define PCIE_REG 0x16 | ||
| 68 | |||
| 69 | #define BUF_SEL_REG 0x20 | ||
| 70 | #define CONF_GEN_SEL_GEN3 0x02 | ||
| 71 | #define CONF_GEN_SEL_GEN2 0x01 | ||
| 72 | #define PD_VDDTFILTER BIT(4) | ||
| 73 | |||
| 74 | #define TXBUF1_REG 0x21 | ||
| 75 | #define SWING_VAL 0x04 | ||
| 76 | #define SWING_VAL_GEN1 0x03 | ||
| 77 | #define PREEMPH_VAL (0x3 << 5) | ||
| 78 | |||
| 79 | #define TXBUF2_REG 0x22 | ||
| 80 | #define TXSLEW_VAL 0x2 | ||
| 81 | #define TXSLEW_VAL_GEN1 0x4 | ||
| 82 | |||
| 83 | #define RXBUF_OFFSET_CTRL_REG 0x23 | ||
| 84 | |||
| 85 | #define RXBUF_REG 0x25 | ||
| 86 | #define SDTHRES_VAL 0x01 | ||
| 87 | #define EQ_ON3 (0x03 << 4) | ||
| 88 | #define EQ_ON1 (0x01 << 4) | ||
| 89 | |||
| 90 | #define COMP_CTRL1_REG 0x40 | ||
| 91 | #define START_COMSR BIT(0) | ||
| 92 | #define START_COMZC BIT(1) | ||
| 93 | #define COMSR_DONE BIT(2) | ||
| 94 | #define COMZC_DONE BIT(3) | ||
| 95 | #define COMP_AUTO_LOAD BIT(4) | ||
| 96 | |||
| 97 | #define COMP_CTRL2_REG 0x41 | ||
| 98 | #define COMP_2MHZ_RAT_GEN1 0x1e | ||
| 99 | #define COMP_2MHZ_RAT 0xf | ||
| 100 | |||
| 101 | #define COMP_CTRL3_REG 0x42 | ||
| 102 | #define COMSR_COMP_REF 0x33 | ||
| 103 | |||
| 104 | #define COMP_IDLL_REG 0x47 | ||
| 105 | #define COMZC_IDLL 0x2a | ||
| 106 | |||
| 107 | #define PLL_CTRL1_REG 0x50 | ||
| 108 | #define PLL_START_CAL BIT(0) | ||
| 109 | #define BUF_EN BIT(2) | ||
| 110 | #define SYNCHRO_TX BIT(3) | ||
| 111 | #define SSC_EN BIT(6) | ||
| 112 | #define CONFIG_PLL BIT(7) | ||
| 113 | |||
| 114 | #define PLL_CTRL2_REG 0x51 | ||
| 115 | #define BYPASS_PLL_CAL BIT(1) | ||
| 116 | |||
| 117 | #define PLL_RAT_REG 0x52 | ||
| 118 | |||
| 119 | #define PLL_SSC_STEP_MSB_REG 0x56 | ||
| 120 | #define PLL_SSC_STEP_MSB_VAL 0x03 | ||
| 121 | |||
| 122 | #define PLL_SSC_STEP_LSB_REG 0x57 | ||
| 123 | #define PLL_SSC_STEP_LSB_VAL 0x63 | ||
| 124 | |||
| 125 | #define PLL_SSC_PER_MSB_REG 0x58 | ||
| 126 | #define PLL_SSC_PER_MSB_VAL 0 | ||
| 127 | |||
| 128 | #define PLL_SSC_PER_LSB_REG 0x59 | ||
| 129 | #define PLL_SSC_PER_LSB_VAL 0xf1 | ||
| 130 | |||
| 131 | #define IDLL_TEST_REG 0x72 | ||
| 132 | #define START_CLK_HF BIT(6) | ||
| 133 | |||
| 134 | #define DES_BITLOCK_REG 0x86 | ||
| 135 | #define BIT_LOCK_LEVEL 0x01 | ||
| 136 | #define BIT_LOCK_CNT_512 (0x03 << 5) | ||
| 137 | |||
| 138 | struct miphy365x_phy { | ||
| 139 | struct phy *phy; | ||
| 140 | void __iomem *base; | ||
| 141 | bool pcie_tx_pol_inv; | ||
| 142 | bool sata_tx_pol_inv; | ||
| 143 | u32 sata_gen; | ||
| 144 | u64 ctrlreg; | ||
| 145 | u8 type; | ||
| 146 | }; | ||
| 147 | |||
| 148 | struct miphy365x_dev { | ||
| 149 | struct device *dev; | ||
| 150 | struct regmap *regmap; | ||
| 151 | struct mutex miphy_mutex; | ||
| 152 | struct miphy365x_phy **phys; | ||
| 153 | }; | ||
| 154 | |||
| 155 | /* | ||
| 156 | * These values are represented in Device tree. They are considered to be ABI | ||
| 157 | * and although they can be extended any existing values must not change. | ||
| 158 | */ | ||
| 159 | enum miphy_sata_gen { | ||
| 160 | SATA_GEN1 = 1, | ||
| 161 | SATA_GEN2, | ||
| 162 | SATA_GEN3 | ||
| 163 | }; | ||
| 164 | |||
| 165 | static u8 rx_tx_spd[] = { | ||
| 166 | TX_SPDSEL_GEN1_VAL | RX_SPDSEL_GEN1_VAL, | ||
| 167 | TX_SPDSEL_GEN2_VAL | RX_SPDSEL_GEN2_VAL, | ||
| 168 | TX_SPDSEL_GEN3_VAL | RX_SPDSEL_GEN3_VAL | ||
| 169 | }; | ||
| 170 | |||
| 171 | /* | ||
| 172 | * This function selects the system configuration, | ||
| 173 | * either two SATA, one SATA and one PCIe, or two PCIe lanes. | ||
| 174 | */ | ||
| 175 | static int miphy365x_set_path(struct miphy365x_phy *miphy_phy, | ||
| 176 | struct miphy365x_dev *miphy_dev) | ||
| 177 | { | ||
| 178 | bool sata = (miphy_phy->type == MIPHY_TYPE_SATA); | ||
| 179 | |||
| 180 | return regmap_update_bits(miphy_dev->regmap, | ||
| 181 | (unsigned int)miphy_phy->ctrlreg, | ||
| 182 | SYSCFG_SELECT_SATA_MASK, | ||
| 183 | sata << SYSCFG_SELECT_SATA_POS); | ||
| 184 | } | ||
| 185 | |||
| 186 | static int miphy365x_init_pcie_port(struct miphy365x_phy *miphy_phy, | ||
| 187 | struct miphy365x_dev *miphy_dev) | ||
| 188 | { | ||
| 189 | u8 val; | ||
| 190 | |||
| 191 | if (miphy_phy->pcie_tx_pol_inv) { | ||
| 192 | /* Invert Tx polarity and clear pci_txdetect_pol bit */ | ||
| 193 | val = TERM_EN | PCI_EN | DES_BIT_LOCK_EN | TX_POL; | ||
| 194 | writeb_relaxed(val, miphy_phy->base + CTRL_REG); | ||
| 195 | writeb_relaxed(0x00, miphy_phy->base + PCIE_REG); | ||
| 196 | } | ||
| 197 | |||
| 198 | return 0; | ||
| 199 | } | ||
| 200 | |||
| 201 | static inline int miphy365x_hfc_not_rdy(struct miphy365x_phy *miphy_phy, | ||
| 202 | struct miphy365x_dev *miphy_dev) | ||
| 203 | { | ||
| 204 | unsigned long timeout = jiffies + msecs_to_jiffies(HFC_TIMEOUT); | ||
| 205 | u8 mask = IDLL_RDY | PLL_RDY; | ||
| 206 | u8 regval; | ||
| 207 | |||
| 208 | do { | ||
| 209 | regval = readb_relaxed(miphy_phy->base + STATUS_REG); | ||
| 210 | if (!(regval & mask)) | ||
| 211 | return 0; | ||
| 212 | |||
| 213 | usleep_range(2000, 2500); | ||
| 214 | } while (time_before(jiffies, timeout)); | ||
| 215 | |||
| 216 | dev_err(miphy_dev->dev, "HFC ready timeout!\n"); | ||
| 217 | return -EBUSY; | ||
| 218 | } | ||
| 219 | |||
| 220 | static inline int miphy365x_rdy(struct miphy365x_phy *miphy_phy, | ||
| 221 | struct miphy365x_dev *miphy_dev) | ||
| 222 | { | ||
| 223 | unsigned long timeout = jiffies + msecs_to_jiffies(HFC_TIMEOUT); | ||
| 224 | u8 mask = IDLL_RDY | PLL_RDY; | ||
| 225 | u8 regval; | ||
| 226 | |||
| 227 | do { | ||
| 228 | regval = readb_relaxed(miphy_phy->base + STATUS_REG); | ||
| 229 | if ((regval & mask) == mask) | ||
| 230 | return 0; | ||
| 231 | |||
| 232 | usleep_range(2000, 2500); | ||
| 233 | } while (time_before(jiffies, timeout)); | ||
| 234 | |||
| 235 | dev_err(miphy_dev->dev, "PHY not ready timeout!\n"); | ||
| 236 | return -EBUSY; | ||
| 237 | } | ||
| 238 | |||
| 239 | static inline void miphy365x_set_comp(struct miphy365x_phy *miphy_phy, | ||
| 240 | struct miphy365x_dev *miphy_dev) | ||
| 241 | { | ||
| 242 | u8 val, mask; | ||
| 243 | |||
| 244 | if (miphy_phy->sata_gen == SATA_GEN1) | ||
| 245 | writeb_relaxed(COMP_2MHZ_RAT_GEN1, | ||
| 246 | miphy_phy->base + COMP_CTRL2_REG); | ||
| 247 | else | ||
| 248 | writeb_relaxed(COMP_2MHZ_RAT, | ||
| 249 | miphy_phy->base + COMP_CTRL2_REG); | ||
| 250 | |||
| 251 | if (miphy_phy->sata_gen != SATA_GEN3) { | ||
| 252 | writeb_relaxed(COMSR_COMP_REF, | ||
| 253 | miphy_phy->base + COMP_CTRL3_REG); | ||
| 254 | /* | ||
| 255 | * Force VCO current to value defined by address 0x5A | ||
| 256 | * and disable PCIe100Mref bit | ||
| 257 | * Enable auto load compensation for pll_i_bias | ||
| 258 | */ | ||
| 259 | writeb_relaxed(BYPASS_PLL_CAL, miphy_phy->base + PLL_CTRL2_REG); | ||
| 260 | writeb_relaxed(COMZC_IDLL, miphy_phy->base + COMP_IDLL_REG); | ||
| 261 | } | ||
| 262 | |||
| 263 | /* | ||
| 264 | * Force restart compensation and enable auto load | ||
| 265 | * for Comzc_Tx, Comzc_Rx and Comsr on macro | ||
| 266 | */ | ||
| 267 | val = START_COMSR | START_COMZC | COMP_AUTO_LOAD; | ||
| 268 | writeb_relaxed(val, miphy_phy->base + COMP_CTRL1_REG); | ||
| 269 | |||
| 270 | mask = COMSR_DONE | COMZC_DONE; | ||
| 271 | while ((readb_relaxed(miphy_phy->base + COMP_CTRL1_REG) & mask) != mask) | ||
| 272 | cpu_relax(); | ||
| 273 | } | ||
| 274 | |||
| 275 | static inline void miphy365x_set_ssc(struct miphy365x_phy *miphy_phy, | ||
| 276 | struct miphy365x_dev *miphy_dev) | ||
| 277 | { | ||
| 278 | u8 val; | ||
| 279 | |||
| 280 | /* | ||
| 281 | * SSC Settings. SSC will be enabled through Link | ||
| 282 | * SSC Ampl. = 0.4% | ||
| 283 | * SSC Freq = 31KHz | ||
| 284 | */ | ||
| 285 | writeb_relaxed(PLL_SSC_STEP_MSB_VAL, | ||
| 286 | miphy_phy->base + PLL_SSC_STEP_MSB_REG); | ||
| 287 | writeb_relaxed(PLL_SSC_STEP_LSB_VAL, | ||
| 288 | miphy_phy->base + PLL_SSC_STEP_LSB_REG); | ||
| 289 | writeb_relaxed(PLL_SSC_PER_MSB_VAL, | ||
| 290 | miphy_phy->base + PLL_SSC_PER_MSB_REG); | ||
| 291 | writeb_relaxed(PLL_SSC_PER_LSB_VAL, | ||
| 292 | miphy_phy->base + PLL_SSC_PER_LSB_REG); | ||
| 293 | |||
| 294 | /* SSC Settings complete */ | ||
| 295 | if (miphy_phy->sata_gen == SATA_GEN1) { | ||
| 296 | val = PLL_START_CAL | BUF_EN | SYNCHRO_TX | CONFIG_PLL; | ||
| 297 | writeb_relaxed(val, miphy_phy->base + PLL_CTRL1_REG); | ||
| 298 | } else { | ||
| 299 | val = SSC_EN | PLL_START_CAL | BUF_EN | SYNCHRO_TX | CONFIG_PLL; | ||
| 300 | writeb_relaxed(val, miphy_phy->base + PLL_CTRL1_REG); | ||
| 301 | } | ||
| 302 | } | ||
| 303 | |||
| 304 | static int miphy365x_init_sata_port(struct miphy365x_phy *miphy_phy, | ||
| 305 | struct miphy365x_dev *miphy_dev) | ||
| 306 | { | ||
| 307 | int ret; | ||
| 308 | u8 val; | ||
| 309 | |||
| 310 | /* | ||
| 311 | * Force PHY macro reset, PLL calibration reset, PLL reset | ||
| 312 | * and assert Deserializer Reset | ||
| 313 | */ | ||
| 314 | val = RST_PLL | RST_PLL_CAL | RST_RX | RST_MACRO; | ||
| 315 | writeb_relaxed(val, miphy_phy->base + RESET_REG); | ||
| 316 | |||
| 317 | if (miphy_phy->sata_tx_pol_inv) | ||
| 318 | writeb_relaxed(TX_POL, miphy_phy->base + CTRL_REG); | ||
| 319 | |||
| 320 | /* | ||
| 321 | * Force macro1 to use rx_lspd, tx_lspd | ||
| 322 | * Force Rx_Clock on first I-DLL phase | ||
| 323 | * Force Des in HP mode on macro, rx_lspd, tx_lspd for Gen2/3 | ||
| 324 | */ | ||
| 325 | writeb_relaxed(SPDSEL_SEL, miphy_phy->base + BOUNDARY1_REG); | ||
| 326 | writeb_relaxed(START_CLK_HF, miphy_phy->base + IDLL_TEST_REG); | ||
| 327 | val = rx_tx_spd[miphy_phy->sata_gen]; | ||
| 328 | writeb_relaxed(val, miphy_phy->base + BOUNDARY3_REG); | ||
| 329 | |||
| 330 | /* Wait for HFC_READY = 0 */ | ||
| 331 | ret = miphy365x_hfc_not_rdy(miphy_phy, miphy_dev); | ||
| 332 | if (ret) | ||
| 333 | return ret; | ||
| 334 | |||
| 335 | /* Compensation Recalibration */ | ||
| 336 | miphy365x_set_comp(miphy_phy, miphy_dev); | ||
| 337 | |||
| 338 | switch (miphy_phy->sata_gen) { | ||
| 339 | case SATA_GEN3: | ||
| 340 | /* | ||
| 341 | * TX Swing target 550-600mv peak to peak diff | ||
| 342 | * Tx Slew target 90-110ps rising/falling time | ||
| 343 | * Rx Eq ON3, Sigdet threshold SDTH1 | ||
| 344 | */ | ||
| 345 | val = PD_VDDTFILTER | CONF_GEN_SEL_GEN3; | ||
| 346 | writeb_relaxed(val, miphy_phy->base + BUF_SEL_REG); | ||
| 347 | val = SWING_VAL | PREEMPH_VAL; | ||
| 348 | writeb_relaxed(val, miphy_phy->base + TXBUF1_REG); | ||
| 349 | writeb_relaxed(TXSLEW_VAL, miphy_phy->base + TXBUF2_REG); | ||
| 350 | writeb_relaxed(0x00, miphy_phy->base + RXBUF_OFFSET_CTRL_REG); | ||
| 351 | val = SDTHRES_VAL | EQ_ON3; | ||
| 352 | writeb_relaxed(val, miphy_phy->base + RXBUF_REG); | ||
| 353 | break; | ||
| 354 | case SATA_GEN2: | ||
| 355 | /* | ||
| 356 | * conf gen sel=0x1 to program Gen2 banked registers | ||
| 357 | * VDDT filter ON | ||
| 358 | * Tx Swing target 550-600mV peak-to-peak diff | ||
| 359 | * Tx Slew target 90-110 ps rising/falling time | ||
| 360 | * RX Equalization ON1, Sigdet threshold SDTH1 | ||
| 361 | */ | ||
| 362 | writeb_relaxed(CONF_GEN_SEL_GEN2, | ||
| 363 | miphy_phy->base + BUF_SEL_REG); | ||
| 364 | writeb_relaxed(SWING_VAL, miphy_phy->base + TXBUF1_REG); | ||
| 365 | writeb_relaxed(TXSLEW_VAL, miphy_phy->base + TXBUF2_REG); | ||
| 366 | val = SDTHRES_VAL | EQ_ON1; | ||
| 367 | writeb_relaxed(val, miphy_phy->base + RXBUF_REG); | ||
| 368 | break; | ||
| 369 | case SATA_GEN1: | ||
| 370 | /* | ||
| 371 | * conf gen sel = 00b to program Gen1 banked registers | ||
| 372 | * VDDT filter ON | ||
| 373 | * Tx Swing target 500-550mV peak-to-peak diff | ||
| 374 | * Tx Slew target120-140 ps rising/falling time | ||
| 375 | */ | ||
| 376 | writeb_relaxed(PD_VDDTFILTER, miphy_phy->base + BUF_SEL_REG); | ||
| 377 | writeb_relaxed(SWING_VAL_GEN1, miphy_phy->base + TXBUF1_REG); | ||
| 378 | writeb_relaxed(TXSLEW_VAL_GEN1, miphy_phy->base + TXBUF2_REG); | ||
| 379 | break; | ||
| 380 | default: | ||
| 381 | break; | ||
| 382 | } | ||
| 383 | |||
| 384 | /* Force Macro1 in partial mode & release pll cal reset */ | ||
| 385 | writeb_relaxed(RST_RX, miphy_phy->base + RESET_REG); | ||
| 386 | usleep_range(100, 150); | ||
| 387 | |||
| 388 | miphy365x_set_ssc(miphy_phy, miphy_dev); | ||
| 389 | |||
| 390 | /* Wait for phy_ready */ | ||
| 391 | ret = miphy365x_rdy(miphy_phy, miphy_dev); | ||
| 392 | if (ret) | ||
| 393 | return ret; | ||
| 394 | |||
| 395 | /* | ||
| 396 | * Enable macro1 to use rx_lspd & tx_lspd | ||
| 397 | * Release Rx_Clock on first I-DLL phase on macro1 | ||
| 398 | * Assert deserializer reset | ||
| 399 | * des_bit_lock_en is set | ||
| 400 | * bit lock detection strength | ||
| 401 | * Deassert deserializer reset | ||
| 402 | */ | ||
| 403 | writeb_relaxed(0x00, miphy_phy->base + BOUNDARY1_REG); | ||
| 404 | writeb_relaxed(0x00, miphy_phy->base + IDLL_TEST_REG); | ||
| 405 | writeb_relaxed(RST_RX, miphy_phy->base + RESET_REG); | ||
| 406 | val = miphy_phy->sata_tx_pol_inv ? | ||
| 407 | (TX_POL | DES_BIT_LOCK_EN) : DES_BIT_LOCK_EN; | ||
| 408 | writeb_relaxed(val, miphy_phy->base + CTRL_REG); | ||
| 409 | |||
| 410 | val = BIT_LOCK_CNT_512 | BIT_LOCK_LEVEL; | ||
| 411 | writeb_relaxed(val, miphy_phy->base + DES_BITLOCK_REG); | ||
| 412 | writeb_relaxed(0x00, miphy_phy->base + RESET_REG); | ||
| 413 | |||
| 414 | return 0; | ||
| 415 | } | ||
| 416 | |||
| 417 | static int miphy365x_init(struct phy *phy) | ||
| 418 | { | ||
| 419 | struct miphy365x_phy *miphy_phy = phy_get_drvdata(phy); | ||
| 420 | struct miphy365x_dev *miphy_dev = dev_get_drvdata(phy->dev.parent); | ||
| 421 | int ret = 0; | ||
| 422 | |||
| 423 | mutex_lock(&miphy_dev->miphy_mutex); | ||
| 424 | |||
| 425 | ret = miphy365x_set_path(miphy_phy, miphy_dev); | ||
| 426 | if (ret) { | ||
| 427 | mutex_unlock(&miphy_dev->miphy_mutex); | ||
| 428 | return ret; | ||
| 429 | } | ||
| 430 | |||
| 431 | /* Initialise Miphy for PCIe or SATA */ | ||
| 432 | if (miphy_phy->type == MIPHY_TYPE_PCIE) | ||
| 433 | ret = miphy365x_init_pcie_port(miphy_phy, miphy_dev); | ||
| 434 | else | ||
| 435 | ret = miphy365x_init_sata_port(miphy_phy, miphy_dev); | ||
| 436 | |||
| 437 | mutex_unlock(&miphy_dev->miphy_mutex); | ||
| 438 | |||
| 439 | return ret; | ||
| 440 | } | ||
| 441 | |||
| 442 | int miphy365x_get_addr(struct device *dev, struct miphy365x_phy *miphy_phy, | ||
| 443 | int index) | ||
| 444 | { | ||
| 445 | struct device_node *phynode = miphy_phy->phy->dev.of_node; | ||
| 446 | const char *name; | ||
| 447 | const __be32 *taddr; | ||
| 448 | int type = miphy_phy->type; | ||
| 449 | int ret; | ||
| 450 | |||
| 451 | ret = of_property_read_string_index(phynode, "reg-names", index, &name); | ||
| 452 | if (ret) { | ||
| 453 | dev_err(dev, "no reg-names property not found\n"); | ||
| 454 | return ret; | ||
| 455 | } | ||
| 456 | |||
| 457 | if (!strncmp(name, "syscfg", 6)) { | ||
| 458 | taddr = of_get_address(phynode, index, NULL, NULL); | ||
| 459 | if (!taddr) { | ||
| 460 | dev_err(dev, "failed to fetch syscfg address\n"); | ||
| 461 | return -EINVAL; | ||
| 462 | } | ||
| 463 | |||
| 464 | miphy_phy->ctrlreg = of_translate_address(phynode, taddr); | ||
| 465 | if (miphy_phy->ctrlreg == OF_BAD_ADDR) { | ||
| 466 | dev_err(dev, "failed to translate syscfg address\n"); | ||
| 467 | return -EINVAL; | ||
| 468 | } | ||
| 469 | |||
| 470 | return 0; | ||
| 471 | } | ||
| 472 | |||
| 473 | if (!((!strncmp(name, "sata", 4) && type == MIPHY_TYPE_SATA) || | ||
| 474 | (!strncmp(name, "pcie", 4) && type == MIPHY_TYPE_PCIE))) | ||
| 475 | return 0; | ||
| 476 | |||
| 477 | miphy_phy->base = of_iomap(phynode, index); | ||
| 478 | if (!miphy_phy->base) { | ||
| 479 | dev_err(dev, "Failed to map %s\n", phynode->full_name); | ||
| 480 | return -EINVAL; | ||
| 481 | } | ||
| 482 | |||
| 483 | return 0; | ||
| 484 | } | ||
| 485 | |||
| 486 | static struct phy *miphy365x_xlate(struct device *dev, | ||
| 487 | struct of_phandle_args *args) | ||
| 488 | { | ||
| 489 | struct miphy365x_dev *miphy_dev = dev_get_drvdata(dev); | ||
| 490 | struct miphy365x_phy *miphy_phy = NULL; | ||
| 491 | struct device_node *phynode = args->np; | ||
| 492 | int ret, index; | ||
| 493 | |||
| 494 | if (!of_device_is_available(phynode)) { | ||
| 495 | dev_warn(dev, "Requested PHY is disabled\n"); | ||
| 496 | return ERR_PTR(-ENODEV); | ||
| 497 | } | ||
| 498 | |||
| 499 | if (args->args_count != 1) { | ||
| 500 | dev_err(dev, "Invalid number of cells in 'phy' property\n"); | ||
| 501 | return ERR_PTR(-EINVAL); | ||
| 502 | } | ||
| 503 | |||
| 504 | for (index = 0; index < of_get_child_count(dev->of_node); index++) | ||
| 505 | if (phynode == miphy_dev->phys[index]->phy->dev.of_node) { | ||
| 506 | miphy_phy = miphy_dev->phys[index]; | ||
| 507 | break; | ||
| 508 | } | ||
| 509 | |||
| 510 | if (!miphy_phy) { | ||
| 511 | dev_err(dev, "Failed to find appropriate phy\n"); | ||
| 512 | return ERR_PTR(-EINVAL); | ||
| 513 | } | ||
| 514 | |||
| 515 | miphy_phy->type = args->args[0]; | ||
| 516 | |||
| 517 | if (!(miphy_phy->type == MIPHY_TYPE_SATA || | ||
| 518 | miphy_phy->type == MIPHY_TYPE_PCIE)) { | ||
| 519 | dev_err(dev, "Unsupported device type: %d\n", miphy_phy->type); | ||
| 520 | return ERR_PTR(-EINVAL); | ||
| 521 | } | ||
| 522 | |||
| 523 | /* Each port handles SATA and PCIE - third entry is always sysconf. */ | ||
| 524 | for (index = 0; index < 3; index++) { | ||
| 525 | ret = miphy365x_get_addr(dev, miphy_phy, index); | ||
| 526 | if (ret < 0) | ||
| 527 | return ERR_PTR(ret); | ||
| 528 | } | ||
| 529 | |||
| 530 | return miphy_phy->phy; | ||
| 531 | } | ||
| 532 | |||
| 533 | static struct phy_ops miphy365x_ops = { | ||
| 534 | .init = miphy365x_init, | ||
| 535 | .owner = THIS_MODULE, | ||
| 536 | }; | ||
| 537 | |||
| 538 | static int miphy365x_of_probe(struct device_node *phynode, | ||
| 539 | struct miphy365x_phy *miphy_phy) | ||
| 540 | { | ||
| 541 | of_property_read_u32(phynode, "st,sata-gen", &miphy_phy->sata_gen); | ||
| 542 | if (!miphy_phy->sata_gen) | ||
| 543 | miphy_phy->sata_gen = SATA_GEN1; | ||
| 544 | |||
| 545 | miphy_phy->pcie_tx_pol_inv = | ||
| 546 | of_property_read_bool(phynode, "st,pcie-tx-pol-inv"); | ||
| 547 | |||
| 548 | miphy_phy->sata_tx_pol_inv = | ||
| 549 | of_property_read_bool(phynode, "st,sata-tx-pol-inv"); | ||
| 550 | |||
| 551 | return 0; | ||
| 552 | } | ||
| 553 | |||
| 554 | static int miphy365x_probe(struct platform_device *pdev) | ||
| 555 | { | ||
| 556 | struct device_node *child, *np = pdev->dev.of_node; | ||
| 557 | struct miphy365x_dev *miphy_dev; | ||
| 558 | struct phy_provider *provider; | ||
| 559 | struct phy *phy; | ||
| 560 | int chancount, port = 0; | ||
| 561 | int ret; | ||
| 562 | |||
| 563 | miphy_dev = devm_kzalloc(&pdev->dev, sizeof(*miphy_dev), GFP_KERNEL); | ||
| 564 | if (!miphy_dev) | ||
| 565 | return -ENOMEM; | ||
| 566 | |||
| 567 | chancount = of_get_child_count(np); | ||
| 568 | miphy_dev->phys = devm_kzalloc(&pdev->dev, sizeof(phy) * chancount, | ||
| 569 | GFP_KERNEL); | ||
| 570 | if (!miphy_dev->phys) | ||
| 571 | return -ENOMEM; | ||
| 572 | |||
| 573 | miphy_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); | ||
| 574 | if (IS_ERR(miphy_dev->regmap)) { | ||
| 575 | dev_err(miphy_dev->dev, "No syscfg phandle specified\n"); | ||
| 576 | return PTR_ERR(miphy_dev->regmap); | ||
| 577 | } | ||
| 578 | |||
| 579 | miphy_dev->dev = &pdev->dev; | ||
| 580 | |||
| 581 | dev_set_drvdata(&pdev->dev, miphy_dev); | ||
| 582 | |||
| 583 | mutex_init(&miphy_dev->miphy_mutex); | ||
| 584 | |||
| 585 | for_each_child_of_node(np, child) { | ||
| 586 | struct miphy365x_phy *miphy_phy; | ||
| 587 | |||
| 588 | miphy_phy = devm_kzalloc(&pdev->dev, sizeof(*miphy_phy), | ||
| 589 | GFP_KERNEL); | ||
| 590 | if (!miphy_phy) | ||
| 591 | return -ENOMEM; | ||
| 592 | |||
| 593 | miphy_dev->phys[port] = miphy_phy; | ||
| 594 | |||
| 595 | phy = devm_phy_create(&pdev->dev, child, &miphy365x_ops, NULL); | ||
| 596 | if (IS_ERR(phy)) { | ||
| 597 | dev_err(&pdev->dev, "failed to create PHY\n"); | ||
| 598 | return PTR_ERR(phy); | ||
| 599 | } | ||
| 600 | |||
| 601 | miphy_dev->phys[port]->phy = phy; | ||
| 602 | |||
| 603 | ret = miphy365x_of_probe(child, miphy_phy); | ||
| 604 | if (ret) | ||
| 605 | return ret; | ||
| 606 | |||
| 607 | phy_set_drvdata(phy, miphy_dev->phys[port]); | ||
| 608 | port++; | ||
| 609 | } | ||
| 610 | |||
| 611 | provider = devm_of_phy_provider_register(&pdev->dev, miphy365x_xlate); | ||
| 612 | if (IS_ERR(provider)) | ||
| 613 | return PTR_ERR(provider); | ||
| 614 | |||
| 615 | return 0; | ||
| 616 | } | ||
| 617 | |||
| 618 | static const struct of_device_id miphy365x_of_match[] = { | ||
| 619 | { .compatible = "st,miphy365x-phy", }, | ||
| 620 | { }, | ||
| 621 | }; | ||
| 622 | MODULE_DEVICE_TABLE(of, miphy365x_of_match); | ||
| 623 | |||
| 624 | static struct platform_driver miphy365x_driver = { | ||
| 625 | .probe = miphy365x_probe, | ||
| 626 | .driver = { | ||
| 627 | .name = "miphy365x-phy", | ||
| 628 | .owner = THIS_MODULE, | ||
| 629 | .of_match_table = miphy365x_of_match, | ||
| 630 | } | ||
| 631 | }; | ||
| 632 | module_platform_driver(miphy365x_driver); | ||
| 633 | |||
| 634 | MODULE_AUTHOR("Alexandre Torgue <alexandre.torgue@st.com>"); | ||
| 635 | MODULE_DESCRIPTION("STMicroelectronics miphy365x driver"); | ||
| 636 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/phy/phy-mvebu-sata.c b/drivers/phy/phy-mvebu-sata.c index d70ecd6a1b3f..cc3c0e166daf 100644 --- a/drivers/phy/phy-mvebu-sata.c +++ b/drivers/phy/phy-mvebu-sata.c | |||
| @@ -99,7 +99,7 @@ static int phy_mvebu_sata_probe(struct platform_device *pdev) | |||
| 99 | if (IS_ERR(priv->clk)) | 99 | if (IS_ERR(priv->clk)) |
| 100 | return PTR_ERR(priv->clk); | 100 | return PTR_ERR(priv->clk); |
| 101 | 101 | ||
| 102 | phy = devm_phy_create(&pdev->dev, &phy_mvebu_sata_ops, NULL); | 102 | phy = devm_phy_create(&pdev->dev, NULL, &phy_mvebu_sata_ops, NULL); |
| 103 | if (IS_ERR(phy)) | 103 | if (IS_ERR(phy)) |
| 104 | return PTR_ERR(phy); | 104 | return PTR_ERR(phy); |
| 105 | 105 | ||
diff --git a/drivers/phy/phy-omap-control.c b/drivers/phy/phy-omap-control.c index 311b4f9a5132..9487bf112267 100644 --- a/drivers/phy/phy-omap-control.c +++ b/drivers/phy/phy-omap-control.c | |||
| @@ -27,6 +27,41 @@ | |||
| 27 | #include <linux/phy/omap_control_phy.h> | 27 | #include <linux/phy/omap_control_phy.h> |
| 28 | 28 | ||
| 29 | /** | 29 | /** |
| 30 | * omap_control_pcie_pcs - set the PCS delay count | ||
| 31 | * @dev: the control module device | ||
| 32 | * @id: index of the pcie PHY (should be 1 or 2) | ||
| 33 | * @delay: 8 bit delay value | ||
| 34 | */ | ||
| 35 | void omap_control_pcie_pcs(struct device *dev, u8 id, u8 delay) | ||
| 36 | { | ||
| 37 | u32 val; | ||
| 38 | struct omap_control_phy *control_phy; | ||
| 39 | |||
| 40 | if (IS_ERR(dev) || !dev) { | ||
| 41 | pr_err("%s: invalid device\n", __func__); | ||
| 42 | return; | ||
| 43 | } | ||
| 44 | |||
| 45 | control_phy = dev_get_drvdata(dev); | ||
| 46 | if (!control_phy) { | ||
| 47 | dev_err(dev, "%s: invalid control phy device\n", __func__); | ||
| 48 | return; | ||
| 49 | } | ||
| 50 | |||
| 51 | if (control_phy->type != OMAP_CTRL_TYPE_PCIE) { | ||
| 52 | dev_err(dev, "%s: unsupported operation\n", __func__); | ||
| 53 | return; | ||
| 54 | } | ||
| 55 | |||
| 56 | val = readl(control_phy->pcie_pcs); | ||
| 57 | val &= ~(OMAP_CTRL_PCIE_PCS_MASK << | ||
| 58 | (id * OMAP_CTRL_PCIE_PCS_DELAY_COUNT_SHIFT)); | ||
| 59 | val |= delay << (id * OMAP_CTRL_PCIE_PCS_DELAY_COUNT_SHIFT); | ||
| 60 | writel(val, control_phy->pcie_pcs); | ||
| 61 | } | ||
| 62 | EXPORT_SYMBOL_GPL(omap_control_pcie_pcs); | ||
| 63 | |||
| 64 | /** | ||
| 30 | * omap_control_phy_power - power on/off the phy using control module reg | 65 | * omap_control_phy_power - power on/off the phy using control module reg |
| 31 | * @dev: the control module device | 66 | * @dev: the control module device |
| 32 | * @on: 0 or 1, based on powering on or off the PHY | 67 | * @on: 0 or 1, based on powering on or off the PHY |
| @@ -61,6 +96,7 @@ void omap_control_phy_power(struct device *dev, int on) | |||
| 61 | val |= OMAP_CTRL_DEV_PHY_PD; | 96 | val |= OMAP_CTRL_DEV_PHY_PD; |
| 62 | break; | 97 | break; |
| 63 | 98 | ||
| 99 | case OMAP_CTRL_TYPE_PCIE: | ||
| 64 | case OMAP_CTRL_TYPE_PIPE3: | 100 | case OMAP_CTRL_TYPE_PIPE3: |
| 65 | rate = clk_get_rate(control_phy->sys_clk); | 101 | rate = clk_get_rate(control_phy->sys_clk); |
| 66 | rate = rate/1000000; | 102 | rate = rate/1000000; |
| @@ -211,6 +247,7 @@ EXPORT_SYMBOL_GPL(omap_control_usb_set_mode); | |||
| 211 | static const enum omap_control_phy_type otghs_data = OMAP_CTRL_TYPE_OTGHS; | 247 | static const enum omap_control_phy_type otghs_data = OMAP_CTRL_TYPE_OTGHS; |
| 212 | static const enum omap_control_phy_type usb2_data = OMAP_CTRL_TYPE_USB2; | 248 | static const enum omap_control_phy_type usb2_data = OMAP_CTRL_TYPE_USB2; |
| 213 | static const enum omap_control_phy_type pipe3_data = OMAP_CTRL_TYPE_PIPE3; | 249 | static const enum omap_control_phy_type pipe3_data = OMAP_CTRL_TYPE_PIPE3; |
| 250 | static const enum omap_control_phy_type pcie_data = OMAP_CTRL_TYPE_PCIE; | ||
| 214 | static const enum omap_control_phy_type dra7usb2_data = OMAP_CTRL_TYPE_DRA7USB2; | 251 | static const enum omap_control_phy_type dra7usb2_data = OMAP_CTRL_TYPE_DRA7USB2; |
| 215 | static const enum omap_control_phy_type am437usb2_data = OMAP_CTRL_TYPE_AM437USB2; | 252 | static const enum omap_control_phy_type am437usb2_data = OMAP_CTRL_TYPE_AM437USB2; |
| 216 | 253 | ||
| @@ -228,6 +265,10 @@ static const struct of_device_id omap_control_phy_id_table[] = { | |||
| 228 | .data = &pipe3_data, | 265 | .data = &pipe3_data, |
| 229 | }, | 266 | }, |
| 230 | { | 267 | { |
| 268 | .compatible = "ti,control-phy-pcie", | ||
| 269 | .data = &pcie_data, | ||
| 270 | }, | ||
| 271 | { | ||
| 231 | .compatible = "ti,control-phy-usb2-dra7", | 272 | .compatible = "ti,control-phy-usb2-dra7", |
| 232 | .data = &dra7usb2_data, | 273 | .data = &dra7usb2_data, |
| 233 | }, | 274 | }, |
| @@ -279,7 +320,8 @@ static int omap_control_phy_probe(struct platform_device *pdev) | |||
| 279 | } | 320 | } |
| 280 | } | 321 | } |
| 281 | 322 | ||
| 282 | if (control_phy->type == OMAP_CTRL_TYPE_PIPE3) { | 323 | if (control_phy->type == OMAP_CTRL_TYPE_PIPE3 || |
| 324 | control_phy->type == OMAP_CTRL_TYPE_PCIE) { | ||
| 283 | control_phy->sys_clk = devm_clk_get(control_phy->dev, | 325 | control_phy->sys_clk = devm_clk_get(control_phy->dev, |
| 284 | "sys_clkin"); | 326 | "sys_clkin"); |
| 285 | if (IS_ERR(control_phy->sys_clk)) { | 327 | if (IS_ERR(control_phy->sys_clk)) { |
| @@ -288,6 +330,14 @@ static int omap_control_phy_probe(struct platform_device *pdev) | |||
| 288 | } | 330 | } |
| 289 | } | 331 | } |
| 290 | 332 | ||
| 333 | if (control_phy->type == OMAP_CTRL_TYPE_PCIE) { | ||
| 334 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | ||
| 335 | "pcie_pcs"); | ||
| 336 | control_phy->pcie_pcs = devm_ioremap_resource(&pdev->dev, res); | ||
| 337 | if (IS_ERR(control_phy->pcie_pcs)) | ||
| 338 | return PTR_ERR(control_phy->pcie_pcs); | ||
| 339 | } | ||
| 340 | |||
| 291 | dev_set_drvdata(control_phy->dev, control_phy); | 341 | dev_set_drvdata(control_phy->dev, control_phy); |
| 292 | 342 | ||
| 293 | return 0; | 343 | return 0; |
diff --git a/drivers/phy/phy-omap-usb2.c b/drivers/phy/phy-omap-usb2.c index 34b396146c8a..93d78359246c 100644 --- a/drivers/phy/phy-omap-usb2.c +++ b/drivers/phy/phy-omap-usb2.c | |||
| @@ -263,7 +263,7 @@ static int omap_usb2_probe(struct platform_device *pdev) | |||
| 263 | 263 | ||
| 264 | platform_set_drvdata(pdev, phy); | 264 | platform_set_drvdata(pdev, phy); |
| 265 | 265 | ||
| 266 | generic_phy = devm_phy_create(phy->dev, &ops, NULL); | 266 | generic_phy = devm_phy_create(phy->dev, NULL, &ops, NULL); |
| 267 | if (IS_ERR(generic_phy)) | 267 | if (IS_ERR(generic_phy)) |
| 268 | return PTR_ERR(generic_phy); | 268 | return PTR_ERR(generic_phy); |
| 269 | 269 | ||
diff --git a/drivers/phy/phy-qcom-apq8064-sata.c b/drivers/phy/phy-qcom-apq8064-sata.c new file mode 100644 index 000000000000..b3ef7d805765 --- /dev/null +++ b/drivers/phy/phy-qcom-apq8064-sata.c | |||
| @@ -0,0 +1,289 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2014, The Linux Foundation. All rights reserved. | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License version 2 and | ||
| 6 | * only version 2 as published by the Free Software Foundation. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/io.h> | ||
| 15 | #include <linux/kernel.h> | ||
| 16 | #include <linux/module.h> | ||
| 17 | #include <linux/of.h> | ||
| 18 | #include <linux/time.h> | ||
| 19 | #include <linux/delay.h> | ||
| 20 | #include <linux/clk.h> | ||
| 21 | #include <linux/slab.h> | ||
| 22 | #include <linux/platform_device.h> | ||
| 23 | #include <linux/phy/phy.h> | ||
| 24 | |||
| 25 | /* PHY registers */ | ||
| 26 | #define UNIPHY_PLL_REFCLK_CFG 0x000 | ||
| 27 | #define UNIPHY_PLL_PWRGEN_CFG 0x014 | ||
| 28 | #define UNIPHY_PLL_GLB_CFG 0x020 | ||
| 29 | #define UNIPHY_PLL_SDM_CFG0 0x038 | ||
| 30 | #define UNIPHY_PLL_SDM_CFG1 0x03C | ||
| 31 | #define UNIPHY_PLL_SDM_CFG2 0x040 | ||
| 32 | #define UNIPHY_PLL_SDM_CFG3 0x044 | ||
| 33 | #define UNIPHY_PLL_SDM_CFG4 0x048 | ||
| 34 | #define UNIPHY_PLL_SSC_CFG0 0x04C | ||
| 35 | #define UNIPHY_PLL_SSC_CFG1 0x050 | ||
| 36 | #define UNIPHY_PLL_SSC_CFG2 0x054 | ||
| 37 | #define UNIPHY_PLL_SSC_CFG3 0x058 | ||
| 38 | #define UNIPHY_PLL_LKDET_CFG0 0x05C | ||
| 39 | #define UNIPHY_PLL_LKDET_CFG1 0x060 | ||
| 40 | #define UNIPHY_PLL_LKDET_CFG2 0x064 | ||
| 41 | #define UNIPHY_PLL_CAL_CFG0 0x06C | ||
| 42 | #define UNIPHY_PLL_CAL_CFG8 0x08C | ||
| 43 | #define UNIPHY_PLL_CAL_CFG9 0x090 | ||
| 44 | #define UNIPHY_PLL_CAL_CFG10 0x094 | ||
| 45 | #define UNIPHY_PLL_CAL_CFG11 0x098 | ||
| 46 | #define UNIPHY_PLL_STATUS 0x0C0 | ||
| 47 | |||
| 48 | #define SATA_PHY_SER_CTRL 0x100 | ||
| 49 | #define SATA_PHY_TX_DRIV_CTRL0 0x104 | ||
| 50 | #define SATA_PHY_TX_DRIV_CTRL1 0x108 | ||
| 51 | #define SATA_PHY_TX_IMCAL0 0x11C | ||
| 52 | #define SATA_PHY_TX_IMCAL2 0x124 | ||
| 53 | #define SATA_PHY_RX_IMCAL0 0x128 | ||
| 54 | #define SATA_PHY_EQUAL 0x13C | ||
| 55 | #define SATA_PHY_OOB_TERM 0x144 | ||
| 56 | #define SATA_PHY_CDR_CTRL0 0x148 | ||
| 57 | #define SATA_PHY_CDR_CTRL1 0x14C | ||
| 58 | #define SATA_PHY_CDR_CTRL2 0x150 | ||
| 59 | #define SATA_PHY_CDR_CTRL3 0x154 | ||
| 60 | #define SATA_PHY_PI_CTRL0 0x168 | ||
| 61 | #define SATA_PHY_POW_DWN_CTRL0 0x180 | ||
| 62 | #define SATA_PHY_POW_DWN_CTRL1 0x184 | ||
| 63 | #define SATA_PHY_TX_DATA_CTRL 0x188 | ||
| 64 | #define SATA_PHY_ALIGNP 0x1A4 | ||
| 65 | #define SATA_PHY_TX_IMCAL_STAT 0x1E4 | ||
| 66 | #define SATA_PHY_RX_IMCAL_STAT 0x1E8 | ||
| 67 | |||
| 68 | #define UNIPHY_PLL_LOCK BIT(0) | ||
| 69 | #define SATA_PHY_TX_CAL BIT(0) | ||
| 70 | #define SATA_PHY_RX_CAL BIT(0) | ||
| 71 | |||
| 72 | /* default timeout set to 1 sec */ | ||
| 73 | #define TIMEOUT_MS 10000 | ||
| 74 | #define DELAY_INTERVAL_US 100 | ||
| 75 | |||
| 76 | struct qcom_apq8064_sata_phy { | ||
| 77 | void __iomem *mmio; | ||
| 78 | struct clk *cfg_clk; | ||
| 79 | struct device *dev; | ||
| 80 | }; | ||
| 81 | |||
| 82 | /* Helper function to do poll and timeout */ | ||
| 83 | static int read_poll_timeout(void __iomem *addr, u32 mask) | ||
| 84 | { | ||
| 85 | unsigned long timeout = jiffies + msecs_to_jiffies(TIMEOUT_MS); | ||
| 86 | |||
| 87 | do { | ||
| 88 | if (readl_relaxed(addr) & mask) | ||
| 89 | return 0; | ||
| 90 | |||
| 91 | usleep_range(DELAY_INTERVAL_US, DELAY_INTERVAL_US + 50); | ||
| 92 | } while (!time_after(jiffies, timeout)); | ||
| 93 | |||
| 94 | return (readl_relaxed(addr) & mask) ? 0 : -ETIMEDOUT; | ||
| 95 | } | ||
| 96 | |||
| 97 | static int qcom_apq8064_sata_phy_init(struct phy *generic_phy) | ||
| 98 | { | ||
| 99 | struct qcom_apq8064_sata_phy *phy = phy_get_drvdata(generic_phy); | ||
| 100 | void __iomem *base = phy->mmio; | ||
| 101 | int ret = 0; | ||
| 102 | |||
| 103 | /* SATA phy initialization */ | ||
| 104 | writel_relaxed(0x01, base + SATA_PHY_SER_CTRL); | ||
| 105 | writel_relaxed(0xB1, base + SATA_PHY_POW_DWN_CTRL0); | ||
| 106 | /* Make sure the power down happens before power up */ | ||
| 107 | mb(); | ||
| 108 | usleep_range(10, 60); | ||
| 109 | |||
| 110 | writel_relaxed(0x01, base + SATA_PHY_POW_DWN_CTRL0); | ||
| 111 | writel_relaxed(0x3E, base + SATA_PHY_POW_DWN_CTRL1); | ||
| 112 | writel_relaxed(0x01, base + SATA_PHY_RX_IMCAL0); | ||
| 113 | writel_relaxed(0x01, base + SATA_PHY_TX_IMCAL0); | ||
| 114 | writel_relaxed(0x02, base + SATA_PHY_TX_IMCAL2); | ||
| 115 | |||
| 116 | /* Write UNIPHYPLL registers to configure PLL */ | ||
| 117 | writel_relaxed(0x04, base + UNIPHY_PLL_REFCLK_CFG); | ||
| 118 | writel_relaxed(0x00, base + UNIPHY_PLL_PWRGEN_CFG); | ||
| 119 | |||
| 120 | writel_relaxed(0x0A, base + UNIPHY_PLL_CAL_CFG0); | ||
| 121 | writel_relaxed(0xF3, base + UNIPHY_PLL_CAL_CFG8); | ||
| 122 | writel_relaxed(0x01, base + UNIPHY_PLL_CAL_CFG9); | ||
| 123 | writel_relaxed(0xED, base + UNIPHY_PLL_CAL_CFG10); | ||
| 124 | writel_relaxed(0x02, base + UNIPHY_PLL_CAL_CFG11); | ||
| 125 | |||
| 126 | writel_relaxed(0x36, base + UNIPHY_PLL_SDM_CFG0); | ||
| 127 | writel_relaxed(0x0D, base + UNIPHY_PLL_SDM_CFG1); | ||
| 128 | writel_relaxed(0xA3, base + UNIPHY_PLL_SDM_CFG2); | ||
| 129 | writel_relaxed(0xF0, base + UNIPHY_PLL_SDM_CFG3); | ||
| 130 | writel_relaxed(0x00, base + UNIPHY_PLL_SDM_CFG4); | ||
| 131 | |||
| 132 | writel_relaxed(0x19, base + UNIPHY_PLL_SSC_CFG0); | ||
| 133 | writel_relaxed(0xE1, base + UNIPHY_PLL_SSC_CFG1); | ||
| 134 | writel_relaxed(0x00, base + UNIPHY_PLL_SSC_CFG2); | ||
| 135 | writel_relaxed(0x11, base + UNIPHY_PLL_SSC_CFG3); | ||
| 136 | |||
| 137 | writel_relaxed(0x04, base + UNIPHY_PLL_LKDET_CFG0); | ||
| 138 | writel_relaxed(0xFF, base + UNIPHY_PLL_LKDET_CFG1); | ||
| 139 | |||
| 140 | writel_relaxed(0x02, base + UNIPHY_PLL_GLB_CFG); | ||
| 141 | /* make sure global config LDO power down happens before power up */ | ||
| 142 | mb(); | ||
| 143 | |||
| 144 | writel_relaxed(0x03, base + UNIPHY_PLL_GLB_CFG); | ||
| 145 | writel_relaxed(0x05, base + UNIPHY_PLL_LKDET_CFG2); | ||
| 146 | |||
| 147 | /* PLL Lock wait */ | ||
| 148 | ret = read_poll_timeout(base + UNIPHY_PLL_STATUS, UNIPHY_PLL_LOCK); | ||
| 149 | if (ret) { | ||
| 150 | dev_err(phy->dev, "poll timeout UNIPHY_PLL_STATUS\n"); | ||
| 151 | return ret; | ||
| 152 | } | ||
| 153 | |||
| 154 | /* TX Calibration */ | ||
| 155 | ret = read_poll_timeout(base + SATA_PHY_TX_IMCAL_STAT, SATA_PHY_TX_CAL); | ||
| 156 | if (ret) { | ||
| 157 | dev_err(phy->dev, "poll timeout SATA_PHY_TX_IMCAL_STAT\n"); | ||
| 158 | return ret; | ||
| 159 | } | ||
| 160 | |||
| 161 | /* RX Calibration */ | ||
| 162 | ret = read_poll_timeout(base + SATA_PHY_RX_IMCAL_STAT, SATA_PHY_RX_CAL); | ||
| 163 | if (ret) { | ||
| 164 | dev_err(phy->dev, "poll timeout SATA_PHY_RX_IMCAL_STAT\n"); | ||
| 165 | return ret; | ||
| 166 | } | ||
| 167 | |||
| 168 | /* SATA phy calibrated succesfully, power up to functional mode */ | ||
| 169 | writel_relaxed(0x3E, base + SATA_PHY_POW_DWN_CTRL1); | ||
| 170 | writel_relaxed(0x01, base + SATA_PHY_RX_IMCAL0); | ||
| 171 | writel_relaxed(0x01, base + SATA_PHY_TX_IMCAL0); | ||
| 172 | |||
| 173 | writel_relaxed(0x00, base + SATA_PHY_POW_DWN_CTRL1); | ||
| 174 | writel_relaxed(0x59, base + SATA_PHY_CDR_CTRL0); | ||
| 175 | writel_relaxed(0x04, base + SATA_PHY_CDR_CTRL1); | ||
| 176 | writel_relaxed(0x00, base + SATA_PHY_CDR_CTRL2); | ||
| 177 | writel_relaxed(0x00, base + SATA_PHY_PI_CTRL0); | ||
| 178 | writel_relaxed(0x00, base + SATA_PHY_CDR_CTRL3); | ||
| 179 | writel_relaxed(0x01, base + SATA_PHY_POW_DWN_CTRL0); | ||
| 180 | |||
| 181 | writel_relaxed(0x11, base + SATA_PHY_TX_DATA_CTRL); | ||
| 182 | writel_relaxed(0x43, base + SATA_PHY_ALIGNP); | ||
| 183 | writel_relaxed(0x04, base + SATA_PHY_OOB_TERM); | ||
| 184 | |||
| 185 | writel_relaxed(0x01, base + SATA_PHY_EQUAL); | ||
| 186 | writel_relaxed(0x09, base + SATA_PHY_TX_DRIV_CTRL0); | ||
| 187 | writel_relaxed(0x09, base + SATA_PHY_TX_DRIV_CTRL1); | ||
| 188 | |||
| 189 | return 0; | ||
| 190 | } | ||
| 191 | |||
| 192 | static int qcom_apq8064_sata_phy_exit(struct phy *generic_phy) | ||
| 193 | { | ||
| 194 | struct qcom_apq8064_sata_phy *phy = phy_get_drvdata(generic_phy); | ||
| 195 | void __iomem *base = phy->mmio; | ||
| 196 | |||
| 197 | /* Power down PHY */ | ||
| 198 | writel_relaxed(0xF8, base + SATA_PHY_POW_DWN_CTRL0); | ||
| 199 | writel_relaxed(0xFE, base + SATA_PHY_POW_DWN_CTRL1); | ||
| 200 | |||
| 201 | /* Power down PLL block */ | ||
| 202 | writel_relaxed(0x00, base + UNIPHY_PLL_GLB_CFG); | ||
| 203 | |||
| 204 | return 0; | ||
| 205 | } | ||
| 206 | |||
| 207 | static struct phy_ops qcom_apq8064_sata_phy_ops = { | ||
| 208 | .init = qcom_apq8064_sata_phy_init, | ||
| 209 | .exit = qcom_apq8064_sata_phy_exit, | ||
| 210 | .owner = THIS_MODULE, | ||
| 211 | }; | ||
| 212 | |||
| 213 | static int qcom_apq8064_sata_phy_probe(struct platform_device *pdev) | ||
| 214 | { | ||
| 215 | struct qcom_apq8064_sata_phy *phy; | ||
| 216 | struct device *dev = &pdev->dev; | ||
| 217 | struct resource *res; | ||
| 218 | struct phy_provider *phy_provider; | ||
| 219 | struct phy *generic_phy; | ||
| 220 | int ret; | ||
| 221 | |||
| 222 | phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); | ||
| 223 | if (!phy) | ||
| 224 | return -ENOMEM; | ||
| 225 | |||
| 226 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 227 | phy->mmio = devm_ioremap_resource(dev, res); | ||
| 228 | if (IS_ERR(phy->mmio)) | ||
| 229 | return PTR_ERR(phy->mmio); | ||
| 230 | |||
| 231 | generic_phy = devm_phy_create(dev, NULL, &qcom_apq8064_sata_phy_ops, | ||
| 232 | NULL); | ||
| 233 | if (IS_ERR(generic_phy)) { | ||
| 234 | dev_err(dev, "%s: failed to create phy\n", __func__); | ||
| 235 | return PTR_ERR(generic_phy); | ||
| 236 | } | ||
| 237 | |||
| 238 | phy->dev = dev; | ||
| 239 | phy_set_drvdata(generic_phy, phy); | ||
| 240 | platform_set_drvdata(pdev, phy); | ||
| 241 | |||
| 242 | phy->cfg_clk = devm_clk_get(dev, "cfg"); | ||
| 243 | if (IS_ERR(phy->cfg_clk)) { | ||
| 244 | dev_err(dev, "Failed to get sata cfg clock\n"); | ||
| 245 | return PTR_ERR(phy->cfg_clk); | ||
| 246 | } | ||
| 247 | |||
| 248 | ret = clk_prepare_enable(phy->cfg_clk); | ||
| 249 | if (ret) | ||
| 250 | return ret; | ||
| 251 | |||
| 252 | phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); | ||
| 253 | if (IS_ERR(phy_provider)) { | ||
| 254 | clk_disable_unprepare(phy->cfg_clk); | ||
| 255 | dev_err(dev, "%s: failed to register phy\n", __func__); | ||
| 256 | return PTR_ERR(phy_provider); | ||
| 257 | } | ||
| 258 | |||
| 259 | return 0; | ||
| 260 | } | ||
| 261 | |||
| 262 | static int qcom_apq8064_sata_phy_remove(struct platform_device *pdev) | ||
| 263 | { | ||
| 264 | struct qcom_apq8064_sata_phy *phy = platform_get_drvdata(pdev); | ||
| 265 | |||
| 266 | clk_disable_unprepare(phy->cfg_clk); | ||
| 267 | |||
| 268 | return 0; | ||
| 269 | } | ||
| 270 | |||
| 271 | static const struct of_device_id qcom_apq8064_sata_phy_of_match[] = { | ||
| 272 | { .compatible = "qcom,apq8064-sata-phy" }, | ||
| 273 | { }, | ||
| 274 | }; | ||
| 275 | MODULE_DEVICE_TABLE(of, qcom_apq8064_sata_phy_of_match); | ||
| 276 | |||
| 277 | static struct platform_driver qcom_apq8064_sata_phy_driver = { | ||
| 278 | .probe = qcom_apq8064_sata_phy_probe, | ||
| 279 | .remove = qcom_apq8064_sata_phy_remove, | ||
| 280 | .driver = { | ||
| 281 | .name = "qcom-apq8064-sata-phy", | ||
| 282 | .owner = THIS_MODULE, | ||
| 283 | .of_match_table = qcom_apq8064_sata_phy_of_match, | ||
| 284 | } | ||
| 285 | }; | ||
| 286 | module_platform_driver(qcom_apq8064_sata_phy_driver); | ||
| 287 | |||
| 288 | MODULE_DESCRIPTION("QCOM apq8064 SATA PHY driver"); | ||
| 289 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/phy/phy-qcom-ipq806x-sata.c b/drivers/phy/phy-qcom-ipq806x-sata.c new file mode 100644 index 000000000000..909b5a87fc6a --- /dev/null +++ b/drivers/phy/phy-qcom-ipq806x-sata.c | |||
| @@ -0,0 +1,211 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2014, The Linux Foundation. All rights reserved. | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License version 2 and | ||
| 6 | * only version 2 as published by the Free Software Foundation. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/io.h> | ||
| 15 | #include <linux/kernel.h> | ||
| 16 | #include <linux/module.h> | ||
| 17 | #include <linux/of.h> | ||
| 18 | #include <linux/of_address.h> | ||
| 19 | #include <linux/time.h> | ||
| 20 | #include <linux/delay.h> | ||
| 21 | #include <linux/clk.h> | ||
| 22 | #include <linux/slab.h> | ||
| 23 | #include <linux/platform_device.h> | ||
| 24 | #include <linux/phy/phy.h> | ||
| 25 | |||
| 26 | struct qcom_ipq806x_sata_phy { | ||
| 27 | void __iomem *mmio; | ||
| 28 | struct clk *cfg_clk; | ||
| 29 | struct device *dev; | ||
| 30 | }; | ||
| 31 | |||
| 32 | #define __set(v, a, b) (((v) << (b)) & GENMASK(a, b)) | ||
| 33 | |||
| 34 | #define SATA_PHY_P0_PARAM0 0x200 | ||
| 35 | #define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3(x) __set(x, 17, 12) | ||
| 36 | #define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3_MASK GENMASK(17, 12) | ||
| 37 | #define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN2(x) __set(x, 11, 6) | ||
| 38 | #define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN2_MASK GENMASK(11, 6) | ||
| 39 | #define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN1(x) __set(x, 5, 0) | ||
| 40 | #define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN1_MASK GENMASK(5, 0) | ||
| 41 | |||
| 42 | #define SATA_PHY_P0_PARAM1 0x204 | ||
| 43 | #define SATA_PHY_P0_PARAM1_RESERVED_BITS31_21(x) __set(x, 31, 21) | ||
| 44 | #define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3(x) __set(x, 20, 14) | ||
| 45 | #define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3_MASK GENMASK(20, 14) | ||
| 46 | #define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2(x) __set(x, 13, 7) | ||
| 47 | #define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2_MASK GENMASK(13, 7) | ||
| 48 | #define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1(x) __set(x, 6, 0) | ||
| 49 | #define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1_MASK GENMASK(6, 0) | ||
| 50 | |||
| 51 | #define SATA_PHY_P0_PARAM2 0x208 | ||
| 52 | #define SATA_PHY_P0_PARAM2_RX_EQ(x) __set(x, 20, 18) | ||
| 53 | #define SATA_PHY_P0_PARAM2_RX_EQ_MASK GENMASK(20, 18) | ||
| 54 | |||
| 55 | #define SATA_PHY_P0_PARAM3 0x20C | ||
| 56 | #define SATA_PHY_SSC_EN 0x8 | ||
| 57 | #define SATA_PHY_P0_PARAM4 0x210 | ||
| 58 | #define SATA_PHY_REF_SSP_EN 0x2 | ||
| 59 | #define SATA_PHY_RESET 0x1 | ||
| 60 | |||
| 61 | static int qcom_ipq806x_sata_phy_init(struct phy *generic_phy) | ||
| 62 | { | ||
| 63 | struct qcom_ipq806x_sata_phy *phy = phy_get_drvdata(generic_phy); | ||
| 64 | u32 reg; | ||
| 65 | |||
| 66 | /* Setting SSC_EN to 1 */ | ||
| 67 | reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM3); | ||
| 68 | reg = reg | SATA_PHY_SSC_EN; | ||
| 69 | writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM3); | ||
| 70 | |||
| 71 | reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM0) & | ||
| 72 | ~(SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3_MASK | | ||
| 73 | SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN2_MASK | | ||
| 74 | SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN1_MASK); | ||
| 75 | reg |= SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3(0xf); | ||
| 76 | writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM0); | ||
| 77 | |||
| 78 | reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM1) & | ||
| 79 | ~(SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3_MASK | | ||
| 80 | SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2_MASK | | ||
| 81 | SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1_MASK); | ||
| 82 | reg |= SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3(0x55) | | ||
| 83 | SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2(0x55) | | ||
| 84 | SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1(0x55); | ||
| 85 | writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM1); | ||
| 86 | |||
| 87 | reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM2) & | ||
| 88 | ~SATA_PHY_P0_PARAM2_RX_EQ_MASK; | ||
| 89 | reg |= SATA_PHY_P0_PARAM2_RX_EQ(0x3); | ||
| 90 | writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM2); | ||
| 91 | |||
| 92 | /* Setting PHY_RESET to 1 */ | ||
| 93 | reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4); | ||
| 94 | reg = reg | SATA_PHY_RESET; | ||
| 95 | writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4); | ||
| 96 | |||
| 97 | /* Setting REF_SSP_EN to 1 */ | ||
| 98 | reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4); | ||
| 99 | reg = reg | SATA_PHY_REF_SSP_EN | SATA_PHY_RESET; | ||
| 100 | writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4); | ||
| 101 | |||
| 102 | /* make sure all changes complete before we let the PHY out of reset */ | ||
| 103 | mb(); | ||
| 104 | |||
| 105 | /* sleep for max. 50us more to combine processor wakeups */ | ||
| 106 | usleep_range(20, 20 + 50); | ||
| 107 | |||
| 108 | /* Clearing PHY_RESET to 0 */ | ||
| 109 | reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4); | ||
| 110 | reg = reg & ~SATA_PHY_RESET; | ||
| 111 | writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4); | ||
| 112 | |||
| 113 | return 0; | ||
| 114 | } | ||
| 115 | |||
| 116 | static int qcom_ipq806x_sata_phy_exit(struct phy *generic_phy) | ||
| 117 | { | ||
| 118 | struct qcom_ipq806x_sata_phy *phy = phy_get_drvdata(generic_phy); | ||
| 119 | u32 reg; | ||
| 120 | |||
| 121 | /* Setting PHY_RESET to 1 */ | ||
| 122 | reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4); | ||
| 123 | reg = reg | SATA_PHY_RESET; | ||
| 124 | writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4); | ||
| 125 | |||
| 126 | return 0; | ||
| 127 | } | ||
| 128 | |||
| 129 | static struct phy_ops qcom_ipq806x_sata_phy_ops = { | ||
| 130 | .init = qcom_ipq806x_sata_phy_init, | ||
| 131 | .exit = qcom_ipq806x_sata_phy_exit, | ||
| 132 | .owner = THIS_MODULE, | ||
| 133 | }; | ||
| 134 | |||
| 135 | static int qcom_ipq806x_sata_phy_probe(struct platform_device *pdev) | ||
| 136 | { | ||
| 137 | struct qcom_ipq806x_sata_phy *phy; | ||
| 138 | struct device *dev = &pdev->dev; | ||
| 139 | struct resource *res; | ||
| 140 | struct phy_provider *phy_provider; | ||
| 141 | struct phy *generic_phy; | ||
| 142 | int ret; | ||
| 143 | |||
| 144 | phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); | ||
| 145 | if (!phy) | ||
| 146 | return -ENOMEM; | ||
| 147 | |||
| 148 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 149 | phy->mmio = devm_ioremap_resource(dev, res); | ||
| 150 | if (IS_ERR(phy->mmio)) | ||
| 151 | return PTR_ERR(phy->mmio); | ||
| 152 | |||
| 153 | generic_phy = devm_phy_create(dev, NULL, &qcom_ipq806x_sata_phy_ops, | ||
| 154 | NULL); | ||
| 155 | if (IS_ERR(generic_phy)) { | ||
| 156 | dev_err(dev, "%s: failed to create phy\n", __func__); | ||
| 157 | return PTR_ERR(generic_phy); | ||
| 158 | } | ||
| 159 | |||
| 160 | phy->dev = dev; | ||
| 161 | phy_set_drvdata(generic_phy, phy); | ||
| 162 | platform_set_drvdata(pdev, phy); | ||
| 163 | |||
| 164 | phy->cfg_clk = devm_clk_get(dev, "cfg"); | ||
| 165 | if (IS_ERR(phy->cfg_clk)) { | ||
| 166 | dev_err(dev, "Failed to get sata cfg clock\n"); | ||
| 167 | return PTR_ERR(phy->cfg_clk); | ||
| 168 | } | ||
| 169 | |||
| 170 | ret = clk_prepare_enable(phy->cfg_clk); | ||
| 171 | if (ret) | ||
| 172 | return ret; | ||
| 173 | |||
| 174 | phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); | ||
| 175 | if (IS_ERR(phy_provider)) { | ||
| 176 | clk_disable_unprepare(phy->cfg_clk); | ||
| 177 | dev_err(dev, "%s: failed to register phy\n", __func__); | ||
| 178 | return PTR_ERR(phy_provider); | ||
| 179 | } | ||
| 180 | |||
| 181 | return 0; | ||
| 182 | } | ||
| 183 | |||
| 184 | static int qcom_ipq806x_sata_phy_remove(struct platform_device *pdev) | ||
| 185 | { | ||
| 186 | struct qcom_ipq806x_sata_phy *phy = platform_get_drvdata(pdev); | ||
| 187 | |||
| 188 | clk_disable_unprepare(phy->cfg_clk); | ||
| 189 | |||
| 190 | return 0; | ||
| 191 | } | ||
| 192 | |||
| 193 | static const struct of_device_id qcom_ipq806x_sata_phy_of_match[] = { | ||
| 194 | { .compatible = "qcom,ipq806x-sata-phy" }, | ||
| 195 | { }, | ||
| 196 | }; | ||
| 197 | MODULE_DEVICE_TABLE(of, qcom_ipq806x_sata_phy_of_match); | ||
| 198 | |||
| 199 | static struct platform_driver qcom_ipq806x_sata_phy_driver = { | ||
| 200 | .probe = qcom_ipq806x_sata_phy_probe, | ||
| 201 | .remove = qcom_ipq806x_sata_phy_remove, | ||
| 202 | .driver = { | ||
| 203 | .name = "qcom-ipq806x-sata-phy", | ||
| 204 | .owner = THIS_MODULE, | ||
| 205 | .of_match_table = qcom_ipq806x_sata_phy_of_match, | ||
| 206 | } | ||
| 207 | }; | ||
| 208 | module_platform_driver(qcom_ipq806x_sata_phy_driver); | ||
| 209 | |||
| 210 | MODULE_DESCRIPTION("QCOM IPQ806x SATA PHY driver"); | ||
| 211 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/phy/phy-samsung-usb2.c b/drivers/phy/phy-samsung-usb2.c index 1e69a32c221d..ae30640a411d 100644 --- a/drivers/phy/phy-samsung-usb2.c +++ b/drivers/phy/phy-samsung-usb2.c | |||
| @@ -87,6 +87,12 @@ static struct phy *samsung_usb2_phy_xlate(struct device *dev, | |||
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | static const struct of_device_id samsung_usb2_phy_of_match[] = { | 89 | static const struct of_device_id samsung_usb2_phy_of_match[] = { |
| 90 | #ifdef CONFIG_PHY_EXYNOS4X12_USB2 | ||
| 91 | { | ||
| 92 | .compatible = "samsung,exynos3250-usb2-phy", | ||
| 93 | .data = &exynos3250_usb2_phy_config, | ||
| 94 | }, | ||
| 95 | #endif | ||
| 90 | #ifdef CONFIG_PHY_EXYNOS4210_USB2 | 96 | #ifdef CONFIG_PHY_EXYNOS4210_USB2 |
| 91 | { | 97 | { |
| 92 | .compatible = "samsung,exynos4210-usb2-phy", | 98 | .compatible = "samsung,exynos4210-usb2-phy", |
| @@ -190,7 +196,8 @@ static int samsung_usb2_phy_probe(struct platform_device *pdev) | |||
| 190 | struct samsung_usb2_phy_instance *p = &drv->instances[i]; | 196 | struct samsung_usb2_phy_instance *p = &drv->instances[i]; |
| 191 | 197 | ||
| 192 | dev_dbg(dev, "Creating phy \"%s\"\n", label); | 198 | dev_dbg(dev, "Creating phy \"%s\"\n", label); |
| 193 | p->phy = devm_phy_create(dev, &samsung_usb2_phy_ops, NULL); | 199 | p->phy = devm_phy_create(dev, NULL, &samsung_usb2_phy_ops, |
| 200 | NULL); | ||
| 194 | if (IS_ERR(p->phy)) { | 201 | if (IS_ERR(p->phy)) { |
| 195 | dev_err(drv->dev, "Failed to create usb2_phy \"%s\"\n", | 202 | dev_err(drv->dev, "Failed to create usb2_phy \"%s\"\n", |
| 196 | label); | 203 | label); |
diff --git a/drivers/phy/phy-samsung-usb2.h b/drivers/phy/phy-samsung-usb2.h index 45b3170652bd..b03da0ef39ac 100644 --- a/drivers/phy/phy-samsung-usb2.h +++ b/drivers/phy/phy-samsung-usb2.h | |||
| @@ -29,7 +29,8 @@ struct samsung_usb2_phy_instance { | |||
| 29 | const struct samsung_usb2_common_phy *cfg; | 29 | const struct samsung_usb2_common_phy *cfg; |
| 30 | struct phy *phy; | 30 | struct phy *phy; |
| 31 | struct samsung_usb2_phy_driver *drv; | 31 | struct samsung_usb2_phy_driver *drv; |
| 32 | bool enabled; | 32 | int int_cnt; |
| 33 | int ext_cnt; | ||
| 33 | }; | 34 | }; |
| 34 | 35 | ||
| 35 | struct samsung_usb2_phy_driver { | 36 | struct samsung_usb2_phy_driver { |
| @@ -59,8 +60,10 @@ struct samsung_usb2_phy_config { | |||
| 59 | int (*rate_to_clk)(unsigned long, u32 *); | 60 | int (*rate_to_clk)(unsigned long, u32 *); |
| 60 | unsigned int num_phys; | 61 | unsigned int num_phys; |
| 61 | bool has_mode_switch; | 62 | bool has_mode_switch; |
| 63 | bool has_refclk_sel; | ||
| 62 | }; | 64 | }; |
| 63 | 65 | ||
| 66 | extern const struct samsung_usb2_phy_config exynos3250_usb2_phy_config; | ||
| 64 | extern const struct samsung_usb2_phy_config exynos4210_usb2_phy_config; | 67 | extern const struct samsung_usb2_phy_config exynos4210_usb2_phy_config; |
| 65 | extern const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config; | 68 | extern const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config; |
| 66 | extern const struct samsung_usb2_phy_config exynos5250_usb2_phy_config; | 69 | extern const struct samsung_usb2_phy_config exynos5250_usb2_phy_config; |
diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c index 115d8d5190d5..61ebea49709b 100644 --- a/drivers/phy/phy-sun4i-usb.c +++ b/drivers/phy/phy-sun4i-usb.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | */ | 22 | */ |
| 23 | 23 | ||
| 24 | #include <linux/clk.h> | 24 | #include <linux/clk.h> |
| 25 | #include <linux/err.h> | ||
| 25 | #include <linux/io.h> | 26 | #include <linux/io.h> |
| 26 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
| 27 | #include <linux/module.h> | 28 | #include <linux/module.h> |
| @@ -294,7 +295,7 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) | |||
| 294 | return PTR_ERR(phy->pmu); | 295 | return PTR_ERR(phy->pmu); |
| 295 | } | 296 | } |
| 296 | 297 | ||
| 297 | phy->phy = devm_phy_create(dev, &sun4i_usb_phy_ops, NULL); | 298 | phy->phy = devm_phy_create(dev, NULL, &sun4i_usb_phy_ops, NULL); |
| 298 | if (IS_ERR(phy->phy)) { | 299 | if (IS_ERR(phy->phy)) { |
| 299 | dev_err(dev, "failed to create PHY %d\n", i); | 300 | dev_err(dev, "failed to create PHY %d\n", i); |
| 300 | return PTR_ERR(phy->phy); | 301 | return PTR_ERR(phy->phy); |
| @@ -306,10 +307,8 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) | |||
| 306 | 307 | ||
| 307 | dev_set_drvdata(dev, data); | 308 | dev_set_drvdata(dev, data); |
| 308 | phy_provider = devm_of_phy_provider_register(dev, sun4i_usb_phy_xlate); | 309 | phy_provider = devm_of_phy_provider_register(dev, sun4i_usb_phy_xlate); |
| 309 | if (IS_ERR(phy_provider)) | ||
| 310 | return PTR_ERR(phy_provider); | ||
| 311 | 310 | ||
| 312 | return 0; | 311 | return PTR_ERR_OR_ZERO(phy_provider); |
| 313 | } | 312 | } |
| 314 | 313 | ||
| 315 | static const struct of_device_id sun4i_usb_phy_of_match[] = { | 314 | static const struct of_device_id sun4i_usb_phy_of_match[] = { |
diff --git a/drivers/phy/phy-ti-pipe3.c b/drivers/phy/phy-ti-pipe3.c index 591367654613..b964aa967b46 100644 --- a/drivers/phy/phy-ti-pipe3.c +++ b/drivers/phy/phy-ti-pipe3.c | |||
| @@ -80,7 +80,9 @@ struct ti_pipe3 { | |||
| 80 | struct clk *wkupclk; | 80 | struct clk *wkupclk; |
| 81 | struct clk *sys_clk; | 81 | struct clk *sys_clk; |
| 82 | struct clk *refclk; | 82 | struct clk *refclk; |
| 83 | struct clk *div_clk; | ||
| 83 | struct pipe3_dpll_map *dpll_map; | 84 | struct pipe3_dpll_map *dpll_map; |
| 85 | u8 id; | ||
| 84 | }; | 86 | }; |
| 85 | 87 | ||
| 86 | static struct pipe3_dpll_map dpll_map_usb[] = { | 88 | static struct pipe3_dpll_map dpll_map_usb[] = { |
| @@ -215,6 +217,11 @@ static int ti_pipe3_init(struct phy *x) | |||
| 215 | u32 val; | 217 | u32 val; |
| 216 | int ret = 0; | 218 | int ret = 0; |
| 217 | 219 | ||
| 220 | if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie")) { | ||
| 221 | omap_control_pcie_pcs(phy->control_dev, phy->id, 0xF1); | ||
| 222 | return 0; | ||
| 223 | } | ||
| 224 | |||
| 218 | /* Bring it out of IDLE if it is IDLE */ | 225 | /* Bring it out of IDLE if it is IDLE */ |
| 219 | val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); | 226 | val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); |
| 220 | if (val & PLL_IDLE) { | 227 | if (val & PLL_IDLE) { |
| @@ -238,8 +245,11 @@ static int ti_pipe3_exit(struct phy *x) | |||
| 238 | u32 val; | 245 | u32 val; |
| 239 | unsigned long timeout; | 246 | unsigned long timeout; |
| 240 | 247 | ||
| 241 | /* SATA DPLL can't be powered down due to Errata i783 */ | 248 | /* SATA DPLL can't be powered down due to Errata i783 and PCIe |
| 242 | if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata")) | 249 | * does not have internal DPLL |
| 250 | */ | ||
| 251 | if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata") || | ||
| 252 | of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie")) | ||
| 243 | return 0; | 253 | return 0; |
| 244 | 254 | ||
| 245 | /* Put DPLL in IDLE mode */ | 255 | /* Put DPLL in IDLE mode */ |
| @@ -286,32 +296,41 @@ static int ti_pipe3_probe(struct platform_device *pdev) | |||
| 286 | struct device_node *control_node; | 296 | struct device_node *control_node; |
| 287 | struct platform_device *control_pdev; | 297 | struct platform_device *control_pdev; |
| 288 | const struct of_device_id *match; | 298 | const struct of_device_id *match; |
| 289 | 299 | struct clk *clk; | |
| 290 | match = of_match_device(of_match_ptr(ti_pipe3_id_table), &pdev->dev); | ||
| 291 | if (!match) | ||
| 292 | return -EINVAL; | ||
| 293 | 300 | ||
| 294 | phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); | 301 | phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); |
| 295 | if (!phy) { | 302 | if (!phy) { |
| 296 | dev_err(&pdev->dev, "unable to alloc mem for TI PIPE3 PHY\n"); | 303 | dev_err(&pdev->dev, "unable to alloc mem for TI PIPE3 PHY\n"); |
| 297 | return -ENOMEM; | 304 | return -ENOMEM; |
| 298 | } | 305 | } |
| 306 | phy->dev = &pdev->dev; | ||
| 299 | 307 | ||
| 300 | phy->dpll_map = (struct pipe3_dpll_map *)match->data; | 308 | if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie")) { |
| 301 | if (!phy->dpll_map) { | 309 | match = of_match_device(of_match_ptr(ti_pipe3_id_table), |
| 302 | dev_err(&pdev->dev, "no DPLL data\n"); | 310 | &pdev->dev); |
| 303 | return -EINVAL; | 311 | if (!match) |
| 304 | } | 312 | return -EINVAL; |
| 305 | 313 | ||
| 306 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll_ctrl"); | 314 | phy->dpll_map = (struct pipe3_dpll_map *)match->data; |
| 307 | phy->pll_ctrl_base = devm_ioremap_resource(&pdev->dev, res); | 315 | if (!phy->dpll_map) { |
| 308 | if (IS_ERR(phy->pll_ctrl_base)) | 316 | dev_err(&pdev->dev, "no DPLL data\n"); |
| 309 | return PTR_ERR(phy->pll_ctrl_base); | 317 | return -EINVAL; |
| 318 | } | ||
| 310 | 319 | ||
| 311 | phy->dev = &pdev->dev; | 320 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, |
| 321 | "pll_ctrl"); | ||
| 322 | phy->pll_ctrl_base = devm_ioremap_resource(&pdev->dev, res); | ||
| 323 | if (IS_ERR(phy->pll_ctrl_base)) | ||
| 324 | return PTR_ERR(phy->pll_ctrl_base); | ||
| 312 | 325 | ||
| 313 | if (!of_device_is_compatible(node, "ti,phy-pipe3-sata")) { | 326 | phy->sys_clk = devm_clk_get(phy->dev, "sysclk"); |
| 327 | if (IS_ERR(phy->sys_clk)) { | ||
| 328 | dev_err(&pdev->dev, "unable to get sysclk\n"); | ||
| 329 | return -EINVAL; | ||
| 330 | } | ||
| 331 | } | ||
| 314 | 332 | ||
| 333 | if (!of_device_is_compatible(node, "ti,phy-pipe3-sata")) { | ||
| 315 | phy->wkupclk = devm_clk_get(phy->dev, "wkupclk"); | 334 | phy->wkupclk = devm_clk_get(phy->dev, "wkupclk"); |
| 316 | if (IS_ERR(phy->wkupclk)) { | 335 | if (IS_ERR(phy->wkupclk)) { |
| 317 | dev_err(&pdev->dev, "unable to get wkupclk\n"); | 336 | dev_err(&pdev->dev, "unable to get wkupclk\n"); |
| @@ -328,10 +347,38 @@ static int ti_pipe3_probe(struct platform_device *pdev) | |||
| 328 | phy->refclk = ERR_PTR(-ENODEV); | 347 | phy->refclk = ERR_PTR(-ENODEV); |
| 329 | } | 348 | } |
| 330 | 349 | ||
| 331 | phy->sys_clk = devm_clk_get(phy->dev, "sysclk"); | 350 | if (of_device_is_compatible(node, "ti,phy-pipe3-pcie")) { |
| 332 | if (IS_ERR(phy->sys_clk)) { | 351 | if (of_property_read_u8(node, "id", &phy->id) < 0) |
| 333 | dev_err(&pdev->dev, "unable to get sysclk\n"); | 352 | phy->id = 1; |
| 334 | return -EINVAL; | 353 | |
| 354 | clk = devm_clk_get(phy->dev, "dpll_ref"); | ||
| 355 | if (IS_ERR(clk)) { | ||
| 356 | dev_err(&pdev->dev, "unable to get dpll ref clk\n"); | ||
| 357 | return PTR_ERR(clk); | ||
| 358 | } | ||
| 359 | clk_set_rate(clk, 1500000000); | ||
| 360 | |||
| 361 | clk = devm_clk_get(phy->dev, "dpll_ref_m2"); | ||
| 362 | if (IS_ERR(clk)) { | ||
| 363 | dev_err(&pdev->dev, "unable to get dpll ref m2 clk\n"); | ||
| 364 | return PTR_ERR(clk); | ||
| 365 | } | ||
| 366 | clk_set_rate(clk, 100000000); | ||
| 367 | |||
| 368 | clk = devm_clk_get(phy->dev, "phy-div"); | ||
| 369 | if (IS_ERR(clk)) { | ||
| 370 | dev_err(&pdev->dev, "unable to get phy-div clk\n"); | ||
| 371 | return PTR_ERR(clk); | ||
| 372 | } | ||
| 373 | clk_set_rate(clk, 100000000); | ||
| 374 | |||
| 375 | phy->div_clk = devm_clk_get(phy->dev, "div-clk"); | ||
| 376 | if (IS_ERR(phy->div_clk)) { | ||
| 377 | dev_err(&pdev->dev, "unable to get div-clk\n"); | ||
| 378 | return PTR_ERR(phy->div_clk); | ||
| 379 | } | ||
| 380 | } else { | ||
| 381 | phy->div_clk = ERR_PTR(-ENODEV); | ||
| 335 | } | 382 | } |
| 336 | 383 | ||
| 337 | control_node = of_parse_phandle(node, "ctrl-module", 0); | 384 | control_node = of_parse_phandle(node, "ctrl-module", 0); |
| @@ -353,7 +400,7 @@ static int ti_pipe3_probe(struct platform_device *pdev) | |||
| 353 | platform_set_drvdata(pdev, phy); | 400 | platform_set_drvdata(pdev, phy); |
| 354 | pm_runtime_enable(phy->dev); | 401 | pm_runtime_enable(phy->dev); |
| 355 | 402 | ||
| 356 | generic_phy = devm_phy_create(phy->dev, &ops, NULL); | 403 | generic_phy = devm_phy_create(phy->dev, NULL, &ops, NULL); |
| 357 | if (IS_ERR(generic_phy)) | 404 | if (IS_ERR(generic_phy)) |
| 358 | return PTR_ERR(generic_phy); | 405 | return PTR_ERR(generic_phy); |
| 359 | 406 | ||
| @@ -387,6 +434,8 @@ static int ti_pipe3_runtime_suspend(struct device *dev) | |||
| 387 | clk_disable_unprepare(phy->wkupclk); | 434 | clk_disable_unprepare(phy->wkupclk); |
| 388 | if (!IS_ERR(phy->refclk)) | 435 | if (!IS_ERR(phy->refclk)) |
| 389 | clk_disable_unprepare(phy->refclk); | 436 | clk_disable_unprepare(phy->refclk); |
| 437 | if (!IS_ERR(phy->div_clk)) | ||
| 438 | clk_disable_unprepare(phy->div_clk); | ||
| 390 | 439 | ||
| 391 | return 0; | 440 | return 0; |
| 392 | } | 441 | } |
| @@ -412,8 +461,19 @@ static int ti_pipe3_runtime_resume(struct device *dev) | |||
| 412 | } | 461 | } |
| 413 | } | 462 | } |
| 414 | 463 | ||
| 464 | if (!IS_ERR(phy->div_clk)) { | ||
| 465 | ret = clk_prepare_enable(phy->div_clk); | ||
| 466 | if (ret) { | ||
| 467 | dev_err(phy->dev, "Failed to enable div_clk %d\n", ret); | ||
| 468 | goto err3; | ||
| 469 | } | ||
| 470 | } | ||
| 415 | return 0; | 471 | return 0; |
| 416 | 472 | ||
| 473 | err3: | ||
| 474 | if (!IS_ERR(phy->wkupclk)) | ||
| 475 | clk_disable_unprepare(phy->wkupclk); | ||
| 476 | |||
| 417 | err2: | 477 | err2: |
| 418 | if (!IS_ERR(phy->refclk)) | 478 | if (!IS_ERR(phy->refclk)) |
| 419 | clk_disable_unprepare(phy->refclk); | 479 | clk_disable_unprepare(phy->refclk); |
| @@ -446,6 +506,9 @@ static const struct of_device_id ti_pipe3_id_table[] = { | |||
| 446 | .compatible = "ti,phy-pipe3-sata", | 506 | .compatible = "ti,phy-pipe3-sata", |
| 447 | .data = dpll_map_sata, | 507 | .data = dpll_map_sata, |
| 448 | }, | 508 | }, |
| 509 | { | ||
| 510 | .compatible = "ti,phy-pipe3-pcie", | ||
| 511 | }, | ||
| 449 | {} | 512 | {} |
| 450 | }; | 513 | }; |
| 451 | MODULE_DEVICE_TABLE(of, ti_pipe3_id_table); | 514 | MODULE_DEVICE_TABLE(of, ti_pipe3_id_table); |
diff --git a/drivers/phy/phy-twl4030-usb.c b/drivers/phy/phy-twl4030-usb.c index 2e0e9b3774c8..e1a6623d4696 100644 --- a/drivers/phy/phy-twl4030-usb.c +++ b/drivers/phy/phy-twl4030-usb.c | |||
| @@ -695,7 +695,7 @@ static int twl4030_usb_probe(struct platform_device *pdev) | |||
| 695 | otg->set_host = twl4030_set_host; | 695 | otg->set_host = twl4030_set_host; |
| 696 | otg->set_peripheral = twl4030_set_peripheral; | 696 | otg->set_peripheral = twl4030_set_peripheral; |
| 697 | 697 | ||
| 698 | phy = devm_phy_create(twl->dev, &ops, init_data); | 698 | phy = devm_phy_create(twl->dev, NULL, &ops, init_data); |
| 699 | if (IS_ERR(phy)) { | 699 | if (IS_ERR(phy)) { |
| 700 | dev_dbg(&pdev->dev, "Failed to create PHY\n"); | 700 | dev_dbg(&pdev->dev, "Failed to create PHY\n"); |
| 701 | return PTR_ERR(phy); | 701 | return PTR_ERR(phy); |
diff --git a/drivers/phy/phy-xgene.c b/drivers/phy/phy-xgene.c index 4aa1ccd1511f..db809b97219e 100644 --- a/drivers/phy/phy-xgene.c +++ b/drivers/phy/phy-xgene.c | |||
| @@ -1707,7 +1707,7 @@ static int xgene_phy_probe(struct platform_device *pdev) | |||
| 1707 | ctx->dev = &pdev->dev; | 1707 | ctx->dev = &pdev->dev; |
| 1708 | platform_set_drvdata(pdev, ctx); | 1708 | platform_set_drvdata(pdev, ctx); |
| 1709 | 1709 | ||
| 1710 | ctx->phy = devm_phy_create(ctx->dev, &xgene_phy_ops, NULL); | 1710 | ctx->phy = devm_phy_create(ctx->dev, NULL, &xgene_phy_ops, NULL); |
| 1711 | if (IS_ERR(ctx->phy)) { | 1711 | if (IS_ERR(ctx->phy)) { |
| 1712 | dev_dbg(&pdev->dev, "Failed to create PHY\n"); | 1712 | dev_dbg(&pdev->dev, "Failed to create PHY\n"); |
| 1713 | rc = PTR_ERR(ctx->phy); | 1713 | rc = PTR_ERR(ctx->phy); |
