From: Huang, Tao Date: Wed, 11 Nov 2015 06:22:30 +0000 (+0800) Subject: Revert "phy: merge and backport phy core from linux kernel 4.1" X-Git-Tag: firefly_0821_release~3621 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=47e29b3e7089543e5b4903cb0071e79275ecd91b;p=firefly-linux-kernel-4.4.55.git Revert "phy: merge and backport phy core from linux kernel 4.1" This reverts commit 97c16b72f3a2d14ad10d7461b116b29a168b74c2. --- diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index a53bd5b52df9..2a436e607f99 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -15,13 +15,6 @@ config GENERIC_PHY phy users can obtain reference to the PHY. All the users of this framework should select this config. -config PHY_BERLIN_USB - tristate "Marvell Berlin USB PHY Driver" - depends on ARCH_BERLIN && RESET_CONTROLLER && HAS_IOMEM && OF - select GENERIC_PHY - help - Enable this to support the USB PHY on Marvell Berlin SoCs. - config PHY_BERLIN_SATA tristate "Marvell Berlin SATA PHY driver" depends on ARCH_BERLIN && HAS_IOMEM && OF @@ -29,19 +22,6 @@ config PHY_BERLIN_SATA help Enable this to support the SATA PHY on Marvell Berlin SoCs. -config ARMADA375_USBCLUSTER_PHY - def_bool y - depends on MACH_ARMADA_375 || COMPILE_TEST - depends on OF - select GENERIC_PHY - -config PHY_DM816X_USB - tristate "TI dm816x USB PHY driver" - depends on ARCH_OMAP2PLUS - select GENERIC_PHY - help - Enable this for dm816x USB to work. - config PHY_EXYNOS_MIPI_VIDEO tristate "S5P/EXYNOS SoC series MIPI CSI-2/DSI PHY driver" depends on HAS_IOMEM @@ -58,14 +38,6 @@ config PHY_MVEBU_SATA depends on OF select GENERIC_PHY -config PHY_MIPHY28LP - tristate "STMicroelectronics MIPHY28LP PHY driver for STiH407" - depends on ARCH_STI - select GENERIC_PHY - help - Enable this to support the miphy transceiver (for SATA/PCIE/USB3) - that is part of STMicroelectronics STiH407 SoC. - config PHY_MIPHY365X tristate "STMicroelectronics MIPHY365X PHY driver for STiH41x series" depends on ARCH_STI @@ -181,17 +153,6 @@ config PHY_SUN4I_USB This driver controls the entire USB PHY block, both the USB OTG parts, as well as the 2 regular USB 2 host PHYs. -config PHY_SUN9I_USB - tristate "Allwinner sun9i SoC USB PHY driver" - depends on ARCH_SUNXI && HAS_IOMEM && OF - depends on RESET_CONTROLLER - select GENERIC_PHY - help - Enable this to support the transceiver that is part of Allwinner - sun9i SoCs. - - This driver controls each individual USB 2 host PHY. - config PHY_SAMSUNG_USB2 tristate "Samsung USB 2.0 PHY driver" depends on HAS_IOMEM @@ -232,7 +193,7 @@ config PHY_EXYNOS5250_USB2 config PHY_EXYNOS5_USBDRD tristate "Exynos5 SoC series USB DRD PHY driver" - depends on ARCH_EXYNOS && OF + depends on ARCH_EXYNOS5 && OF depends on HAS_IOMEM depends on USB_DWC3_EXYNOS select GENERIC_PHY @@ -257,13 +218,6 @@ config PHY_QCOM_IPQ806X_SATA depends on OF select GENERIC_PHY -config PHY_ROCKCHIP_USB - tristate "Rockchip USB2 PHY Driver" - depends on ARCH_ROCKCHIP && OF - select GENERIC_PHY - help - Enable this to support the Rockchip USB 2.0 PHY. - config PHY_ST_SPEAR1310_MIPHY tristate "ST SPEAR1310-MIPHY driver" select GENERIC_PHY @@ -302,11 +256,4 @@ config PHY_STIH41X_USB Enable this to support the USB transceiver that is part of STMicroelectronics STiH41x SoC series. -config PHY_QCOM_UFS - tristate "Qualcomm UFS PHY driver" - depends on OF && ARCH_MSM - select GENERIC_PHY - help - Support for UFS PHY on QCOM chipsets. - endmenu diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index f12625178780..c4590fce082f 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -3,15 +3,11 @@ # obj-$(CONFIG_GENERIC_PHY) += phy-core.o -obj-$(CONFIG_PHY_BERLIN_USB) += phy-berlin-usb.o obj-$(CONFIG_PHY_BERLIN_SATA) += phy-berlin-sata.o -obj-$(CONFIG_PHY_DM816X_USB) += phy-dm816x-usb.o -obj-$(CONFIG_ARMADA375_USBCLUSTER_PHY) += phy-armada375-usb2.o obj-$(CONFIG_BCM_KONA_USB2_PHY) += phy-bcm-kona-usb2.o obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO) += phy-exynos-dp-video.o obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o -obj-$(CONFIG_PHY_MIPHY28LP) += phy-miphy28lp.o obj-$(CONFIG_PHY_MIPHY365X) += phy-miphy365x.o obj-$(CONFIG_PHY_RCAR_GEN2) += phy-rcar-gen2.o obj-$(CONFIG_OMAP_CONTROL_PHY) += phy-omap-control.o @@ -21,7 +17,6 @@ obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o obj-$(CONFIG_PHY_EXYNOS5250_SATA) += phy-exynos5250-sata.o obj-$(CONFIG_PHY_HIX5HD2_SATA) += phy-hix5hd2-sata.o obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o -obj-$(CONFIG_PHY_SUN9I_USB) += phy-sun9i-usb.o obj-$(CONFIG_PHY_SAMSUNG_USB2) += phy-exynos-usb2.o phy-exynos-usb2-y += phy-samsung-usb2.o phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4210_USB2) += phy-exynos4210-usb2.o @@ -30,13 +25,9 @@ phy-exynos-usb2-$(CONFIG_PHY_EXYNOS5250_USB2) += phy-exynos5250-usb2.o phy-exynos-usb2-$(CONFIG_PHY_S5PV210_USB2) += phy-s5pv210-usb2.o obj-$(CONFIG_PHY_EXYNOS5_USBDRD) += phy-exynos5-usbdrd.o obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o -obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY) += phy-spear1310-miphy.o obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY) += phy-spear1340-miphy.o obj-$(CONFIG_PHY_XGENE) += phy-xgene.o obj-$(CONFIG_PHY_STIH407_USB) += phy-stih407-usb.o obj-$(CONFIG_PHY_STIH41X_USB) += phy-stih41x-usb.o -obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs.o -obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-20nm.o -obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-14nm.o diff --git a/drivers/phy/phy-armada375-usb2.c b/drivers/phy/phy-armada375-usb2.c deleted file mode 100644 index 7c99ca256f05..000000000000 --- a/drivers/phy/phy-armada375-usb2.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * USB cluster support for Armada 375 platform. - * - * Copyright (C) 2014 Marvell - * - * Gregory CLEMENT - * - * This file is licensed under the terms of the GNU General Public - * License version 2 or later. This program is licensed "as is" - * without any warranty of any kind, whether express or implied. - * - * Armada 375 comes with an USB2 host and device controller and an - * USB3 controller. The USB cluster control register allows to manage - * common features of both USB controllers. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define USB2_PHY_CONFIG_DISABLE BIT(0) - -struct armada375_cluster_phy { - struct phy *phy; - void __iomem *reg; - bool use_usb3; - int phy_provided; -}; - -static int armada375_usb_phy_init(struct phy *phy) -{ - struct armada375_cluster_phy *cluster_phy; - u32 reg; - - cluster_phy = dev_get_drvdata(phy->dev.parent); - if (!cluster_phy) - return -ENODEV; - - reg = readl(cluster_phy->reg); - if (cluster_phy->use_usb3) - reg |= USB2_PHY_CONFIG_DISABLE; - else - reg &= ~USB2_PHY_CONFIG_DISABLE; - writel(reg, cluster_phy->reg); - - return 0; -} - -static struct phy_ops armada375_usb_phy_ops = { - .init = armada375_usb_phy_init, - .owner = THIS_MODULE, -}; - -/* - * Only one controller can use this PHY. We shouldn't have the case - * when two controllers want to use this PHY. But if this case occurs - * then we provide a phy to the first one and return an error for the - * next one. This error has also to be an error returned by - * devm_phy_optional_get() so different from ENODEV for USB2. In the - * USB3 case it still optional and we use ENODEV. - */ -static struct phy *armada375_usb_phy_xlate(struct device *dev, - struct of_phandle_args *args) -{ - struct armada375_cluster_phy *cluster_phy = dev_get_drvdata(dev); - - if (!cluster_phy) - return ERR_PTR(-ENODEV); - - /* - * Either the phy had never been requested and then the first - * usb claiming it can get it, or it had already been - * requested in this case, we only allow to use it with the - * same configuration. - */ - if (WARN_ON((cluster_phy->phy_provided != PHY_NONE) && - (cluster_phy->phy_provided != args->args[0]))) { - dev_err(dev, "This PHY has already been provided!\n"); - dev_err(dev, "Check your device tree, only one controller can use it\n."); - if (args->args[0] == PHY_TYPE_USB2) - return ERR_PTR(-EBUSY); - else - return ERR_PTR(-ENODEV); - } - - if (args->args[0] == PHY_TYPE_USB2) - cluster_phy->use_usb3 = false; - else if (args->args[0] == PHY_TYPE_USB3) - cluster_phy->use_usb3 = true; - else { - dev_err(dev, "Invalid PHY mode\n"); - return ERR_PTR(-ENODEV); - } - - /* Store which phy mode is used for next test */ - cluster_phy->phy_provided = args->args[0]; - - return cluster_phy->phy; -} - -static int armada375_usb_phy_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct phy *phy; - struct phy_provider *phy_provider; - void __iomem *usb_cluster_base; - struct resource *res; - struct armada375_cluster_phy *cluster_phy; - - cluster_phy = devm_kzalloc(dev, sizeof(*cluster_phy), GFP_KERNEL); - if (!cluster_phy) - return -ENOMEM; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - usb_cluster_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(usb_cluster_base)) - return PTR_ERR(usb_cluster_base); - - phy = devm_phy_create(dev, NULL, &armada375_usb_phy_ops); - if (IS_ERR(phy)) { - dev_err(dev, "failed to create PHY\n"); - return PTR_ERR(phy); - } - - cluster_phy->phy = phy; - cluster_phy->reg = usb_cluster_base; - - dev_set_drvdata(dev, cluster_phy); - - phy_provider = devm_of_phy_provider_register(&pdev->dev, - armada375_usb_phy_xlate); - return PTR_ERR_OR_ZERO(phy_provider); -} - -static const struct of_device_id of_usb_cluster_table[] = { - { .compatible = "marvell,armada-375-usb-cluster", }, - { /* end of list */ }, -}; -MODULE_DEVICE_TABLE(of, of_usb_cluster_table); - -static struct platform_driver armada375_usb_phy_driver = { - .probe = armada375_usb_phy_probe, - .driver = { - .of_match_table = of_usb_cluster_table, - .name = "armada-375-usb-cluster", - .owner = THIS_MODULE, - } -}; -module_platform_driver(armada375_usb_phy_driver); - -MODULE_DESCRIPTION("Armada 375 USB cluster driver"); -MODULE_AUTHOR("Gregory CLEMENT "); -MODULE_LICENSE("GPL"); diff --git a/drivers/phy/phy-bcm-kona-usb2.c b/drivers/phy/phy-bcm-kona-usb2.c index ef2dc1aab2b9..c1e0ca335c0e 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) platform_set_drvdata(pdev, phy); - gphy = devm_phy_create(dev, NULL, &ops); + gphy = devm_phy_create(dev, NULL, &ops, NULL); if (IS_ERR(gphy)) return PTR_ERR(gphy); diff --git a/drivers/phy/phy-berlin-sata.c b/drivers/phy/phy-berlin-sata.c index 6f3e06d687de..69ced52d72aa 100644 --- a/drivers/phy/phy-berlin-sata.c +++ b/drivers/phy/phy-berlin-sata.c @@ -30,8 +30,7 @@ #define MBUS_WRITE_REQUEST_SIZE_128 (BIT(2) << 16) #define MBUS_READ_REQUEST_SIZE_128 (BIT(2) << 19) -#define BG2_PHY_BASE 0x080 -#define BG2Q_PHY_BASE 0x200 +#define PHY_BASE 0x200 /* register 0x01 */ #define REF_FREF_SEL_25 BIT(0) @@ -62,16 +61,15 @@ struct phy_berlin_priv { struct clk *clk; struct phy_berlin_desc **phys; unsigned nphys; - u32 phy_base; }; -static inline void phy_berlin_sata_reg_setbits(void __iomem *ctrl_reg, - u32 phy_base, u32 reg, u32 mask, u32 val) +static inline void phy_berlin_sata_reg_setbits(void __iomem *ctrl_reg, u32 reg, + u32 mask, u32 val) { u32 regval; /* select register */ - writel(phy_base + reg, ctrl_reg + PORT_VSR_ADDR); + writel(PHY_BASE + reg, ctrl_reg + PORT_VSR_ADDR); /* set bits */ regval = readl(ctrl_reg + PORT_VSR_DATA); @@ -105,20 +103,17 @@ static int phy_berlin_sata_power_on(struct phy *phy) writel(regval, priv->base + HOST_VSA_DATA); /* set PHY mode and ref freq to 25 MHz */ - phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x01, - 0x00ff, REF_FREF_SEL_25 | PHY_MODE_SATA); + phy_berlin_sata_reg_setbits(ctrl_reg, 0x1, 0xff, + REF_FREF_SEL_25 | PHY_MODE_SATA); /* set PHY up to 6 Gbps */ - phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x25, - 0x0c00, PHY_GEN_MAX_6_0); + phy_berlin_sata_reg_setbits(ctrl_reg, 0x25, 0xc00, PHY_GEN_MAX_6_0); /* set 40 bits width */ - phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x23, - 0x0c00, DATA_BIT_WIDTH_40); + phy_berlin_sata_reg_setbits(ctrl_reg, 0x23, 0xc00, DATA_BIT_WIDTH_40); /* use max pll rate */ - phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x02, - 0x0000, USE_MAX_PLL_RATE); + phy_berlin_sata_reg_setbits(ctrl_reg, 0x2, 0x0, USE_MAX_PLL_RATE); /* set Gen3 controller speed */ regval = readl(ctrl_reg + PORT_SCR_CTL); @@ -218,16 +213,11 @@ static int phy_berlin_sata_probe(struct platform_device *pdev) if (priv->nphys == 0) return -ENODEV; - priv->phys = devm_kcalloc(dev, priv->nphys, sizeof(*priv->phys), + priv->phys = devm_kzalloc(dev, priv->nphys * sizeof(*priv->phys), GFP_KERNEL); if (!priv->phys) return -ENOMEM; - if (of_device_is_compatible(dev->of_node, "marvell,berlin2-sata-phy")) - priv->phy_base = BG2_PHY_BASE; - else - priv->phy_base = BG2Q_PHY_BASE; - dev_set_drvdata(dev, priv); spin_lock_init(&priv->lock); @@ -249,7 +239,7 @@ static int phy_berlin_sata_probe(struct platform_device *pdev) if (!phy_desc) return -ENOMEM; - phy = devm_phy_create(dev, NULL, &phy_berlin_sata_ops); + phy = devm_phy_create(dev, NULL, &phy_berlin_sata_ops, NULL); if (IS_ERR(phy)) { dev_err(dev, "failed to create PHY %d\n", phy_id); return PTR_ERR(phy); @@ -268,11 +258,13 @@ static int phy_berlin_sata_probe(struct platform_device *pdev) phy_provider = devm_of_phy_provider_register(dev, phy_berlin_sata_phy_xlate); - return PTR_ERR_OR_ZERO(phy_provider); + if (IS_ERR(phy_provider)) + return PTR_ERR(phy_provider); + + return 0; } static const struct of_device_id phy_berlin_sata_of_match[] = { - { .compatible = "marvell,berlin2-sata-phy" }, { .compatible = "marvell,berlin2q-sata-phy" }, { }, }; diff --git a/drivers/phy/phy-berlin-usb.c b/drivers/phy/phy-berlin-usb.c deleted file mode 100644 index c6fc95b53083..000000000000 --- a/drivers/phy/phy-berlin-usb.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (C) 2014 Marvell Technology Group Ltd. - * - * Antoine Tenart - * Jisheng Zhang - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define USB_PHY_PLL 0x04 -#define USB_PHY_PLL_CONTROL 0x08 -#define USB_PHY_TX_CTRL0 0x10 -#define USB_PHY_TX_CTRL1 0x14 -#define USB_PHY_TX_CTRL2 0x18 -#define USB_PHY_RX_CTRL 0x20 -#define USB_PHY_ANALOG 0x34 - -/* USB_PHY_PLL */ -#define CLK_REF_DIV(x) ((x) << 4) -#define FEEDBACK_CLK_DIV(x) ((x) << 8) - -/* USB_PHY_PLL_CONTROL */ -#define CLK_STABLE BIT(0) -#define PLL_CTRL_PIN BIT(1) -#define PLL_CTRL_REG BIT(2) -#define PLL_ON BIT(3) -#define PHASE_OFF_TOL_125 (0x0 << 5) -#define PHASE_OFF_TOL_250 BIT(5) -#define KVC0_CALIB (0x0 << 9) -#define KVC0_REG_CTRL BIT(9) -#define KVC0_HIGH (0x0 << 10) -#define KVC0_LOW (0x3 << 10) -#define CLK_BLK_EN BIT(13) - -/* USB_PHY_TX_CTRL0 */ -#define EXT_HS_RCAL_EN BIT(3) -#define EXT_FS_RCAL_EN BIT(4) -#define IMPCAL_VTH_DIV(x) ((x) << 5) -#define EXT_RS_RCAL_DIV(x) ((x) << 8) -#define EXT_FS_RCAL_DIV(x) ((x) << 12) - -/* USB_PHY_TX_CTRL1 */ -#define TX_VDD15_14 (0x0 << 4) -#define TX_VDD15_15 BIT(4) -#define TX_VDD15_16 (0x2 << 4) -#define TX_VDD15_17 (0x3 << 4) -#define TX_VDD12_VDD (0x0 << 6) -#define TX_VDD12_11 BIT(6) -#define TX_VDD12_12 (0x2 << 6) -#define TX_VDD12_13 (0x3 << 6) -#define LOW_VDD_EN BIT(8) -#define TX_OUT_AMP(x) ((x) << 9) - -/* USB_PHY_TX_CTRL2 */ -#define TX_CHAN_CTRL_REG(x) ((x) << 0) -#define DRV_SLEWRATE(x) ((x) << 4) -#define IMP_CAL_FS_HS_DLY_0 (0x0 << 6) -#define IMP_CAL_FS_HS_DLY_1 BIT(6) -#define IMP_CAL_FS_HS_DLY_2 (0x2 << 6) -#define IMP_CAL_FS_HS_DLY_3 (0x3 << 6) -#define FS_DRV_EN_MASK(x) ((x) << 8) -#define HS_DRV_EN_MASK(x) ((x) << 12) - -/* USB_PHY_RX_CTRL */ -#define PHASE_FREEZE_DLY_2_CL (0x0 << 0) -#define PHASE_FREEZE_DLY_4_CL BIT(0) -#define ACK_LENGTH_8_CL (0x0 << 2) -#define ACK_LENGTH_12_CL BIT(2) -#define ACK_LENGTH_16_CL (0x2 << 2) -#define ACK_LENGTH_20_CL (0x3 << 2) -#define SQ_LENGTH_3 (0x0 << 4) -#define SQ_LENGTH_6 BIT(4) -#define SQ_LENGTH_9 (0x2 << 4) -#define SQ_LENGTH_12 (0x3 << 4) -#define DISCON_THRESHOLD_260 (0x0 << 6) -#define DISCON_THRESHOLD_270 BIT(6) -#define DISCON_THRESHOLD_280 (0x2 << 6) -#define DISCON_THRESHOLD_290 (0x3 << 6) -#define SQ_THRESHOLD(x) ((x) << 8) -#define LPF_COEF(x) ((x) << 12) -#define INTPL_CUR_10 (0x0 << 14) -#define INTPL_CUR_20 BIT(14) -#define INTPL_CUR_30 (0x2 << 14) -#define INTPL_CUR_40 (0x3 << 14) - -/* USB_PHY_ANALOG */ -#define ANA_PWR_UP BIT(1) -#define ANA_PWR_DOWN BIT(2) -#define V2I_VCO_RATIO(x) ((x) << 7) -#define R_ROTATE_90 (0x0 << 10) -#define R_ROTATE_0 BIT(10) -#define MODE_TEST_EN BIT(11) -#define ANA_TEST_DC_CTRL(x) ((x) << 12) - -static const u32 phy_berlin_pll_dividers[] = { - /* Berlin 2 */ - CLK_REF_DIV(0xc) | FEEDBACK_CLK_DIV(0x54), - /* Berlin 2CD */ - CLK_REF_DIV(0x6) | FEEDBACK_CLK_DIV(0x55), -}; - -struct phy_berlin_usb_priv { - void __iomem *base; - struct reset_control *rst_ctrl; - u32 pll_divider; -}; - -static int phy_berlin_usb_power_on(struct phy *phy) -{ - struct phy_berlin_usb_priv *priv = phy_get_drvdata(phy); - - reset_control_reset(priv->rst_ctrl); - - writel(priv->pll_divider, - priv->base + USB_PHY_PLL); - writel(CLK_STABLE | PLL_CTRL_REG | PHASE_OFF_TOL_250 | KVC0_REG_CTRL | - CLK_BLK_EN, priv->base + USB_PHY_PLL_CONTROL); - writel(V2I_VCO_RATIO(0x5) | R_ROTATE_0 | ANA_TEST_DC_CTRL(0x5), - priv->base + USB_PHY_ANALOG); - writel(PHASE_FREEZE_DLY_4_CL | ACK_LENGTH_16_CL | SQ_LENGTH_12 | - DISCON_THRESHOLD_260 | SQ_THRESHOLD(0xa) | LPF_COEF(0x2) | - INTPL_CUR_30, priv->base + USB_PHY_RX_CTRL); - - writel(TX_VDD12_13 | TX_OUT_AMP(0x3), priv->base + USB_PHY_TX_CTRL1); - writel(EXT_HS_RCAL_EN | IMPCAL_VTH_DIV(0x3) | EXT_RS_RCAL_DIV(0x4), - priv->base + USB_PHY_TX_CTRL0); - - writel(EXT_HS_RCAL_EN | IMPCAL_VTH_DIV(0x3) | EXT_RS_RCAL_DIV(0x4) | - EXT_FS_RCAL_DIV(0x2), priv->base + USB_PHY_TX_CTRL0); - - writel(EXT_HS_RCAL_EN | IMPCAL_VTH_DIV(0x3) | EXT_RS_RCAL_DIV(0x4), - priv->base + USB_PHY_TX_CTRL0); - writel(TX_CHAN_CTRL_REG(0xf) | DRV_SLEWRATE(0x3) | IMP_CAL_FS_HS_DLY_3 | - FS_DRV_EN_MASK(0xd), priv->base + USB_PHY_TX_CTRL2); - - return 0; -} - -static struct phy_ops phy_berlin_usb_ops = { - .power_on = phy_berlin_usb_power_on, - .owner = THIS_MODULE, -}; - -static const struct of_device_id phy_berlin_sata_of_match[] = { - { - .compatible = "marvell,berlin2-usb-phy", - .data = &phy_berlin_pll_dividers[0], - }, - { - .compatible = "marvell,berlin2cd-usb-phy", - .data = &phy_berlin_pll_dividers[1], - }, - { }, -}; -MODULE_DEVICE_TABLE(of, phy_berlin_sata_of_match); - -static int phy_berlin_usb_probe(struct platform_device *pdev) -{ - const struct of_device_id *match = - of_match_device(phy_berlin_sata_of_match, &pdev->dev); - struct phy_berlin_usb_priv *priv; - struct resource *res; - struct phy *phy; - struct phy_provider *phy_provider; - - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(priv->base)) - return PTR_ERR(priv->base); - - priv->rst_ctrl = devm_reset_control_get(&pdev->dev, NULL); - if (IS_ERR(priv->rst_ctrl)) - return PTR_ERR(priv->rst_ctrl); - - priv->pll_divider = *((u32 *)match->data); - - phy = devm_phy_create(&pdev->dev, NULL, &phy_berlin_usb_ops); - if (IS_ERR(phy)) { - dev_err(&pdev->dev, "failed to create PHY\n"); - return PTR_ERR(phy); - } - - platform_set_drvdata(pdev, priv); - phy_set_drvdata(phy, priv); - - phy_provider = - devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate); - return PTR_ERR_OR_ZERO(phy_provider); -} - -static struct platform_driver phy_berlin_usb_driver = { - .probe = phy_berlin_usb_probe, - .driver = { - .name = "phy-berlin-usb", - .owner = THIS_MODULE, - .of_match_table = phy_berlin_sata_of_match, - }, -}; -module_platform_driver(phy_berlin_usb_driver); - -MODULE_AUTHOR("Antoine Tenart "); -MODULE_DESCRIPTION("Marvell Berlin PHY driver for USB"); -MODULE_LICENSE("GPL"); diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index a12d35338313..ff5eec5af817 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -26,7 +26,6 @@ static struct class *phy_class; static DEFINE_MUTEX(phy_provider_mutex); static LIST_HEAD(phy_provider_list); -static LIST_HEAD(phys); static DEFINE_IDA(phy_ida); static void devm_phy_release(struct device *dev, void *res) @@ -55,79 +54,34 @@ static int devm_phy_match(struct device *dev, void *res, void *match_data) return res == match_data; } -/** - * phy_create_lookup() - allocate and register PHY/device association - * @phy: the phy of the association - * @con_id: connection ID string on device - * @dev_id: the device of the association - * - * Creates and registers phy_lookup entry. - */ -int phy_create_lookup(struct phy *phy, const char *con_id, const char *dev_id) +static struct phy *phy_lookup(struct device *device, const char *port) { - struct phy_lookup *pl; - - if (!phy || !dev_id || !con_id) - return -EINVAL; - - pl = kzalloc(sizeof(*pl), GFP_KERNEL); - if (!pl) - return -ENOMEM; - - pl->dev_id = dev_id; - pl->con_id = con_id; - pl->phy = phy; - - mutex_lock(&phy_provider_mutex); - list_add_tail(&pl->node, &phys); - mutex_unlock(&phy_provider_mutex); - - return 0; -} -EXPORT_SYMBOL_GPL(phy_create_lookup); - -/** - * phy_remove_lookup() - find and remove PHY/device association - * @phy: the phy of the association - * @con_id: connection ID string on device - * @dev_id: the device of the association - * - * Finds and unregisters phy_lookup entry that was created with - * phy_create_lookup(). - */ -void phy_remove_lookup(struct phy *phy, const char *con_id, const char *dev_id) -{ - struct phy_lookup *pl; - - if (!phy || !dev_id || !con_id) - return; - - mutex_lock(&phy_provider_mutex); - list_for_each_entry(pl, &phys, node) - if (pl->phy == phy && !strcmp(pl->dev_id, dev_id) && - !strcmp(pl->con_id, con_id)) { - list_del(&pl->node); - kfree(pl); - break; - } - mutex_unlock(&phy_provider_mutex); -} -EXPORT_SYMBOL_GPL(phy_remove_lookup); + unsigned int count; + struct phy *phy; + struct device *dev; + struct phy_consumer *consumers; + struct class_dev_iter iter; -static struct phy *phy_find(struct device *dev, const char *con_id) -{ - const char *dev_id = dev_name(dev); - struct phy_lookup *p, *pl = NULL; + class_dev_iter_init(&iter, phy_class, NULL, NULL); + while ((dev = class_dev_iter_next(&iter))) { + phy = to_phy(dev); - mutex_lock(&phy_provider_mutex); - list_for_each_entry(p, &phys, node) - if (!strcmp(p->dev_id, dev_id) && !strcmp(p->con_id, con_id)) { - pl = p; - break; + if (!phy->init_data) + continue; + count = phy->init_data->num_consumers; + consumers = phy->init_data->consumers; + while (count--) { + if (!strcmp(consumers->dev_name, dev_name(device)) && + !strcmp(consumers->port, port)) { + class_dev_iter_exit(&iter); + return phy; + } + consumers++; } - mutex_unlock(&phy_provider_mutex); + } - return pl ? pl->phy : ERR_PTR(-ENODEV); + class_dev_iter_exit(&iter); + return ERR_PTR(-ENODEV); } static struct phy_provider *of_phy_provider_lookup(struct device_node *node) @@ -460,13 +414,21 @@ struct phy *of_phy_simple_xlate(struct device *dev, struct of_phandle_args { struct phy *phy; struct class_dev_iter iter; + struct device_node *node = dev->of_node; + struct device_node *child; class_dev_iter_init(&iter, phy_class, NULL, NULL); while ((dev = class_dev_iter_next(&iter))) { phy = to_phy(dev); - if (args->np != phy->dev.of_node) + if (node != phy->dev.of_node) { + for_each_child_of_node(node, child) { + if (child == phy->dev.of_node) + goto phy_found; + } continue; + } +phy_found: class_dev_iter_exit(&iter); return phy; } @@ -501,7 +463,7 @@ struct phy *phy_get(struct device *dev, const char *string) string); phy = _of_phy_get(dev->of_node, index); } else { - phy = phy_find(dev, string); + phy = phy_lookup(dev, string); } if (IS_ERR(phy)) return phy; @@ -626,11 +588,13 @@ EXPORT_SYMBOL_GPL(devm_of_phy_get); * @dev: device that is creating the new phy * @node: device node of the phy * @ops: function pointers for performing phy operations + * @init_data: contains the list of PHY consumers or NULL * * Called to create a phy using phy framework. */ struct phy *phy_create(struct device *dev, struct device_node *node, - const struct phy_ops *ops) + const struct phy_ops *ops, + struct phy_init_data *init_data) { int ret; int id; @@ -668,6 +632,7 @@ struct phy *phy_create(struct device *dev, struct device_node *node, phy->dev.of_node = node ?: dev->of_node; phy->id = id; phy->ops = ops; + phy->init_data = init_data; ret = dev_set_name(&phy->dev, "phy-%s.%d", dev_name(dev), id); if (ret) @@ -702,6 +667,7 @@ EXPORT_SYMBOL_GPL(phy_create); * @dev: device that is creating the new phy * @node: device node of the phy * @ops: function pointers for performing phy operations + * @init_data: contains the list of PHY consumers or NULL * * Creates a new PHY device adding it to the PHY class. * While at that, it also associates the device with the phy using devres. @@ -709,7 +675,8 @@ EXPORT_SYMBOL_GPL(phy_create); * then, devres data is freed. */ struct phy *devm_phy_create(struct device *dev, struct device_node *node, - const struct phy_ops *ops) + const struct phy_ops *ops, + struct phy_init_data *init_data) { struct phy **ptr, *phy; @@ -717,7 +684,7 @@ struct phy *devm_phy_create(struct device *dev, struct device_node *node, if (!ptr) return ERR_PTR(-ENOMEM); - phy = phy_create(dev, node, ops); + phy = phy_create(dev, node, ops, init_data); if (!IS_ERR(phy)) { *ptr = phy; devres_add(dev, ptr); diff --git a/drivers/phy/phy-dm816x-usb.c b/drivers/phy/phy-dm816x-usb.c deleted file mode 100644 index 7b42555ddd51..000000000000 --- a/drivers/phy/phy-dm816x-usb.c +++ /dev/null @@ -1,290 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any - * kind, whether express or implied; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/* - * TRM has two sets of USB_CTRL registers.. The correct register bits - * are in TRM section 24.9.8.2 USB_CTRL Register. The TRM documents the - * phy as being SR70LX Synopsys USB 2.0 OTG nanoPHY. It also seems at - * least dm816x rev c ignores writes to USB_CTRL register, but the TI - * kernel is writing to those so it's possible that later revisions - * have worknig USB_CTRL register. - * - * Also note that At least USB_CTRL register seems to be dm816x specific - * according to the TRM. It's possible that USBPHY_CTRL is more generic, - * but that would have to be checked against the SR70LX documentation - * which does not seem to be publicly available. - * - * Finally, the phy on dm814x and am335x is different from dm816x. - */ -#define DM816X_USB_CTRL_PHYCLKSRC BIT(8) /* 1 = PLL ref clock */ -#define DM816X_USB_CTRL_PHYSLEEP1 BIT(1) /* Enable the first phy */ -#define DM816X_USB_CTRL_PHYSLEEP0 BIT(0) /* Enable the second phy */ - -#define DM816X_USBPHY_CTRL_TXRISETUNE 1 -#define DM816X_USBPHY_CTRL_TXVREFTUNE 0xc -#define DM816X_USBPHY_CTRL_TXPREEMTUNE 0x2 - -struct dm816x_usb_phy { - struct regmap *syscon; - struct device *dev; - unsigned int instance; - struct clk *refclk; - struct usb_phy phy; - unsigned int usb_ctrl; /* Shared between phy0 and phy1 */ - unsigned int usbphy_ctrl; -}; - -static int dm816x_usb_phy_set_host(struct usb_otg *otg, struct usb_bus *host) -{ - otg->host = host; - if (!host) - otg->state = OTG_STATE_UNDEFINED; - - return 0; -} - -static int dm816x_usb_phy_set_peripheral(struct usb_otg *otg, - struct usb_gadget *gadget) -{ - otg->gadget = gadget; - if (!gadget) - otg->state = OTG_STATE_UNDEFINED; - - return 0; -} - -static int dm816x_usb_phy_init(struct phy *x) -{ - struct dm816x_usb_phy *phy = phy_get_drvdata(x); - unsigned int val; - int error; - - if (clk_get_rate(phy->refclk) != 24000000) - dev_warn(phy->dev, "nonstandard phy refclk\n"); - - /* Set PLL ref clock and put phys to sleep */ - error = regmap_update_bits(phy->syscon, phy->usb_ctrl, - DM816X_USB_CTRL_PHYCLKSRC | - DM816X_USB_CTRL_PHYSLEEP1 | - DM816X_USB_CTRL_PHYSLEEP0, - 0); - regmap_read(phy->syscon, phy->usb_ctrl, &val); - if ((val & 3) != 0) - dev_info(phy->dev, - "Working dm816x USB_CTRL! (0x%08x)\n", - val); - - /* - * TI kernel sets these values for "symmetrical eye diagram and - * better signal quality" so let's assume somebody checked the - * values with a scope and set them here too. - */ - regmap_read(phy->syscon, phy->usbphy_ctrl, &val); - val |= DM816X_USBPHY_CTRL_TXRISETUNE | - DM816X_USBPHY_CTRL_TXVREFTUNE | - DM816X_USBPHY_CTRL_TXPREEMTUNE; - regmap_write(phy->syscon, phy->usbphy_ctrl, val); - - return 0; -} - -static struct phy_ops ops = { - .init = dm816x_usb_phy_init, - .owner = THIS_MODULE, -}; - -static int dm816x_usb_phy_runtime_suspend(struct device *dev) -{ - struct dm816x_usb_phy *phy = dev_get_drvdata(dev); - unsigned int mask, val; - int error = 0; - - mask = BIT(phy->instance); - val = ~BIT(phy->instance); - error = regmap_update_bits(phy->syscon, phy->usb_ctrl, - mask, val); - if (error) - dev_err(phy->dev, "phy%i failed to power off\n", - phy->instance); - clk_disable(phy->refclk); - - return 0; -} - -static int dm816x_usb_phy_runtime_resume(struct device *dev) -{ - struct dm816x_usb_phy *phy = dev_get_drvdata(dev); - unsigned int mask, val; - int error; - - error = clk_enable(phy->refclk); - if (error) - return error; - - /* - * Note that at least dm816x rev c does not seem to do - * anything with the USB_CTRL register. But let's follow - * what the TI tree is doing in case later revisions use - * USB_CTRL. - */ - mask = BIT(phy->instance); - val = BIT(phy->instance); - error = regmap_update_bits(phy->syscon, phy->usb_ctrl, - mask, val); - if (error) { - dev_err(phy->dev, "phy%i failed to power on\n", - phy->instance); - clk_disable(phy->refclk); - return error; - } - - return 0; -} - -static UNIVERSAL_DEV_PM_OPS(dm816x_usb_phy_pm_ops, - dm816x_usb_phy_runtime_suspend, - dm816x_usb_phy_runtime_resume, - NULL); - -#ifdef CONFIG_OF -static const struct of_device_id dm816x_usb_phy_id_table[] = { - { - .compatible = "ti,dm8168-usb-phy", - }, - {}, -}; -MODULE_DEVICE_TABLE(of, dm816x_usb_phy_id_table); -#endif - -static int dm816x_usb_phy_probe(struct platform_device *pdev) -{ - struct dm816x_usb_phy *phy; - struct resource *res; - struct phy *generic_phy; - struct phy_provider *phy_provider; - struct usb_otg *otg; - const struct of_device_id *of_id; - const struct usb_phy_data *phy_data; - int error; - - of_id = of_match_device(of_match_ptr(dm816x_usb_phy_id_table), - &pdev->dev); - if (!of_id) - return -EINVAL; - - phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); - if (!phy) - return -ENOMEM; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENOENT; - - phy->syscon = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, - "syscon"); - if (IS_ERR(phy->syscon)) - return PTR_ERR(phy->syscon); - - /* - * According to sprs614e.pdf, the first usb_ctrl is shared and - * the second instance for usb_ctrl is reserved.. Also the - * register bits are different from earlier TRMs. - */ - phy->usb_ctrl = 0x20; - phy->usbphy_ctrl = (res->start & 0xff) + 4; - if (phy->usbphy_ctrl == 0x2c) - phy->instance = 1; - - phy_data = of_id->data; - - otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL); - if (!otg) - return -ENOMEM; - - phy->dev = &pdev->dev; - phy->phy.dev = phy->dev; - phy->phy.label = "dm8168_usb_phy"; - phy->phy.otg = otg; - phy->phy.type = USB_PHY_TYPE_USB2; - otg->set_host = dm816x_usb_phy_set_host; - otg->set_peripheral = dm816x_usb_phy_set_peripheral; - otg->usb_phy = &phy->phy; - - platform_set_drvdata(pdev, phy); - - phy->refclk = devm_clk_get(phy->dev, "refclk"); - if (IS_ERR(phy->refclk)) - return PTR_ERR(phy->refclk); - error = clk_prepare(phy->refclk); - if (error) - return error; - - pm_runtime_enable(phy->dev); - generic_phy = devm_phy_create(phy->dev, NULL, &ops); - if (IS_ERR(generic_phy)) - return PTR_ERR(generic_phy); - - phy_set_drvdata(generic_phy, phy); - - phy_provider = devm_of_phy_provider_register(phy->dev, - of_phy_simple_xlate); - if (IS_ERR(phy_provider)) - return PTR_ERR(phy_provider); - - usb_add_phy_dev(&phy->phy); - - return 0; -} - -static int dm816x_usb_phy_remove(struct platform_device *pdev) -{ - struct dm816x_usb_phy *phy = platform_get_drvdata(pdev); - - usb_remove_phy(&phy->phy); - pm_runtime_disable(phy->dev); - clk_unprepare(phy->refclk); - - return 0; -} - -static struct platform_driver dm816x_usb_phy_driver = { - .probe = dm816x_usb_phy_probe, - .remove = dm816x_usb_phy_remove, - .driver = { - .name = "dm816x-usb-phy", - .pm = &dm816x_usb_phy_pm_ops, - .of_match_table = of_match_ptr(dm816x_usb_phy_id_table), - }, -}; - -module_platform_driver(dm816x_usb_phy_driver); - -MODULE_ALIAS("platform:dm816x_usb"); -MODULE_AUTHOR("Tony Lindgren "); -MODULE_DESCRIPTION("dm816x usb phy driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/phy/phy-exynos-dp-video.c b/drivers/phy/phy-exynos-dp-video.c index f86cbe68ddaf..84f49e5a3f24 100644 --- a/drivers/phy/phy-exynos-dp-video.c +++ b/drivers/phy/phy-exynos-dp-video.c @@ -112,7 +112,7 @@ static int exynos_dp_video_phy_probe(struct platform_device *pdev) match = of_match_node(exynos_dp_video_phy_of_match, dev->of_node); state->drvdata = match->data; - phy = devm_phy_create(dev, NULL, &exynos_dp_video_phy_ops); + phy = devm_phy_create(dev, NULL, &exynos_dp_video_phy_ops, NULL); if (IS_ERR(phy)) { dev_err(dev, "failed to create Display Port PHY\n"); return PTR_ERR(phy); diff --git a/drivers/phy/phy-exynos-mipi-video.c b/drivers/phy/phy-exynos-mipi-video.c index f017b2f2a54e..6a9bef138617 100644 --- a/drivers/phy/phy-exynos-mipi-video.c +++ b/drivers/phy/phy-exynos-mipi-video.c @@ -12,18 +12,19 @@ #include #include #include -#include #include #include #include #include #include -#include #include -#include -/* MIPI_PHYn_CONTROL reg. offset (for base address from ioremap): n = 0..1 */ +/* MIPI_PHYn_CONTROL register offset: n = 0..1 */ #define EXYNOS_MIPI_PHY_CONTROL(n) ((n) * 4) +#define EXYNOS_MIPI_PHY_ENABLE (1 << 0) +#define EXYNOS_MIPI_PHY_SRESETN (1 << 1) +#define EXYNOS_MIPI_PHY_MRESETN (1 << 2) +#define EXYNOS_MIPI_PHY_RESET_MASK (3 << 1) enum exynos_mipi_phy_id { EXYNOS_MIPI_PHY_ID_CSIS0, @@ -37,62 +38,43 @@ enum exynos_mipi_phy_id { ((id) == EXYNOS_MIPI_PHY_ID_DSIM0 || (id) == EXYNOS_MIPI_PHY_ID_DSIM1) struct exynos_mipi_video_phy { + spinlock_t slock; struct video_phy_desc { struct phy *phy; unsigned int index; } phys[EXYNOS_MIPI_PHYS_NUM]; - spinlock_t slock; void __iomem *regs; - struct mutex mutex; - struct regmap *regmap; }; static int __set_phy_state(struct exynos_mipi_video_phy *state, enum exynos_mipi_phy_id id, unsigned int on) { - const unsigned int offset = EXYNOS4_MIPI_PHY_CONTROL(id / 2); void __iomem *addr; - u32 val, reset; + u32 reg, reset; + + addr = state->regs + EXYNOS_MIPI_PHY_CONTROL(id / 2); if (is_mipi_dsim_phy_id(id)) - reset = EXYNOS4_MIPI_PHY_MRESETN; + reset = EXYNOS_MIPI_PHY_MRESETN; else - reset = EXYNOS4_MIPI_PHY_SRESETN; - - if (state->regmap) { - mutex_lock(&state->mutex); - regmap_read(state->regmap, offset, &val); - if (on) - val |= reset; - else - val &= ~reset; - regmap_write(state->regmap, offset, val); - if (on) - val |= EXYNOS4_MIPI_PHY_ENABLE; - else if (!(val & EXYNOS4_MIPI_PHY_RESET_MASK)) - val &= ~EXYNOS4_MIPI_PHY_ENABLE; - regmap_write(state->regmap, offset, val); - mutex_unlock(&state->mutex); - } else { - addr = state->regs + EXYNOS_MIPI_PHY_CONTROL(id / 2); - - spin_lock(&state->slock); - val = readl(addr); - if (on) - val |= reset; - else - val &= ~reset; - writel(val, addr); - /* Clear ENABLE bit only if MRESETN, SRESETN bits are not set */ - if (on) - val |= EXYNOS4_MIPI_PHY_ENABLE; - else if (!(val & EXYNOS4_MIPI_PHY_RESET_MASK)) - val &= ~EXYNOS4_MIPI_PHY_ENABLE; - - writel(val, addr); - spin_unlock(&state->slock); - } + reset = EXYNOS_MIPI_PHY_SRESETN; + spin_lock(&state->slock); + reg = readl(addr); + if (on) + reg |= reset; + else + reg &= ~reset; + writel(reg, addr); + + /* Clear ENABLE bit only if MRESETN, SRESETN bits are not set. */ + if (on) + reg |= EXYNOS_MIPI_PHY_ENABLE; + else if (!(reg & EXYNOS_MIPI_PHY_RESET_MASK)) + reg &= ~EXYNOS_MIPI_PHY_ENABLE; + + writel(reg, addr); + spin_unlock(&state->slock); return 0; } @@ -136,6 +118,7 @@ static int exynos_mipi_video_phy_probe(struct platform_device *pdev) { struct exynos_mipi_video_phy *state; struct device *dev = &pdev->dev; + struct resource *res; struct phy_provider *phy_provider; unsigned int i; @@ -143,26 +126,18 @@ static int exynos_mipi_video_phy_probe(struct platform_device *pdev) if (!state) return -ENOMEM; - state->regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon"); - if (IS_ERR(state->regmap)) { - struct resource *res; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - dev_info(dev, "regmap lookup failed: %ld\n", - PTR_ERR(state->regmap)); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - state->regs = devm_ioremap_resource(dev, res); - if (IS_ERR(state->regs)) - return PTR_ERR(state->regs); - } + state->regs = devm_ioremap_resource(dev, res); + if (IS_ERR(state->regs)) + return PTR_ERR(state->regs); dev_set_drvdata(dev, state); spin_lock_init(&state->slock); - mutex_init(&state->mutex); for (i = 0; i < EXYNOS_MIPI_PHYS_NUM; i++) { struct phy *phy = devm_phy_create(dev, NULL, - &exynos_mipi_video_phy_ops); + &exynos_mipi_video_phy_ops, NULL); if (IS_ERR(phy)) { dev_err(dev, "failed to create PHY %d\n", i); return PTR_ERR(phy); diff --git a/drivers/phy/phy-exynos5-usbdrd.c b/drivers/phy/phy-exynos5-usbdrd.c index 597e7dd3782a..f756aca871db 100644 --- a/drivers/phy/phy-exynos5-usbdrd.c +++ b/drivers/phy/phy-exynos5-usbdrd.c @@ -141,7 +141,6 @@ struct exynos5_usbdrd_phy_drvdata { const struct exynos5_usbdrd_phy_config *phy_cfg; u32 pmu_offset_usbdrd0_phy; u32 pmu_offset_usbdrd1_phy; - bool has_common_clk_gate; }; /** @@ -149,9 +148,6 @@ struct exynos5_usbdrd_phy_drvdata { * @dev: pointer to device instance of this platform device * @reg_phy: usb phy controller register memory base * @clk: phy clock for register access - * @pipeclk: clock for pipe3 phy - * @utmiclk: clock for utmi+ phy - * @itpclk: clock for ITP generation * @drv_data: pointer to SoC level driver data structure * @phys[]: array for 'EXYNOS5_DRDPHYS_NUM' number of PHY * instances each with its 'phy' and 'phy_cfg'. @@ -159,16 +155,12 @@ struct exynos5_usbdrd_phy_drvdata { * reference clocks' for SS and HS operations * @ref_clk: reference clock to PHY block from which PHY's * operational clocks are derived - * vbus: VBUS regulator for phy - * vbus_boost: Boost regulator for VBUS present on few Exynos boards + * @ref_rate: rate of above reference clock */ struct exynos5_usbdrd_phy { struct device *dev; void __iomem *reg_phy; struct clk *clk; - struct clk *pipeclk; - struct clk *utmiclk; - struct clk *itpclk; const struct exynos5_usbdrd_phy_drvdata *drv_data; struct phy_usb_instance { struct phy *phy; @@ -180,7 +172,6 @@ struct exynos5_usbdrd_phy { u32 extrefclk; struct clk *ref_clk; struct regulator *vbus; - struct regulator *vbus_boost; }; static inline @@ -456,27 +447,13 @@ static int exynos5_usbdrd_phy_power_on(struct phy *phy) dev_dbg(phy_drd->dev, "Request to power_on usbdrd_phy phy\n"); clk_prepare_enable(phy_drd->ref_clk); - if (!phy_drd->drv_data->has_common_clk_gate) { - clk_prepare_enable(phy_drd->pipeclk); - clk_prepare_enable(phy_drd->utmiclk); - clk_prepare_enable(phy_drd->itpclk); - } /* Enable VBUS supply */ - if (phy_drd->vbus_boost) { - ret = regulator_enable(phy_drd->vbus_boost); - if (ret) { - dev_err(phy_drd->dev, - "Failed to enable VBUS boost supply\n"); - goto fail_vbus; - } - } - if (phy_drd->vbus) { ret = regulator_enable(phy_drd->vbus); if (ret) { dev_err(phy_drd->dev, "Failed to enable VBUS supply\n"); - goto fail_vbus_boost; + goto fail_vbus; } } @@ -485,17 +462,8 @@ static int exynos5_usbdrd_phy_power_on(struct phy *phy) return 0; -fail_vbus_boost: - if (phy_drd->vbus_boost) - regulator_disable(phy_drd->vbus_boost); - fail_vbus: clk_disable_unprepare(phy_drd->ref_clk); - if (!phy_drd->drv_data->has_common_clk_gate) { - clk_disable_unprepare(phy_drd->itpclk); - clk_disable_unprepare(phy_drd->utmiclk); - clk_disable_unprepare(phy_drd->pipeclk); - } return ret; } @@ -513,15 +481,8 @@ static int exynos5_usbdrd_phy_power_off(struct phy *phy) /* Disable VBUS supply */ if (phy_drd->vbus) regulator_disable(phy_drd->vbus); - if (phy_drd->vbus_boost) - regulator_disable(phy_drd->vbus_boost); clk_disable_unprepare(phy_drd->ref_clk); - if (!phy_drd->drv_data->has_common_clk_gate) { - clk_disable_unprepare(phy_drd->itpclk); - clk_disable_unprepare(phy_drd->pipeclk); - clk_disable_unprepare(phy_drd->utmiclk); - } return 0; } @@ -545,57 +506,6 @@ static struct phy_ops exynos5_usbdrd_phy_ops = { .owner = THIS_MODULE, }; -static int exynos5_usbdrd_phy_clk_handle(struct exynos5_usbdrd_phy *phy_drd) -{ - unsigned long ref_rate; - int ret; - - phy_drd->clk = devm_clk_get(phy_drd->dev, "phy"); - if (IS_ERR(phy_drd->clk)) { - dev_err(phy_drd->dev, "Failed to get phy clock\n"); - return PTR_ERR(phy_drd->clk); - } - - phy_drd->ref_clk = devm_clk_get(phy_drd->dev, "ref"); - if (IS_ERR(phy_drd->ref_clk)) { - dev_err(phy_drd->dev, "Failed to get phy reference clock\n"); - return PTR_ERR(phy_drd->ref_clk); - } - ref_rate = clk_get_rate(phy_drd->ref_clk); - - ret = exynos5_rate_to_clk(ref_rate, &phy_drd->extrefclk); - if (ret) { - dev_err(phy_drd->dev, "Clock rate (%ld) not supported\n", - ref_rate); - return ret; - } - - if (!phy_drd->drv_data->has_common_clk_gate) { - phy_drd->pipeclk = devm_clk_get(phy_drd->dev, "phy_pipe"); - if (IS_ERR(phy_drd->pipeclk)) { - dev_info(phy_drd->dev, - "PIPE3 phy operational clock not specified\n"); - phy_drd->pipeclk = NULL; - } - - phy_drd->utmiclk = devm_clk_get(phy_drd->dev, "phy_utmi"); - if (IS_ERR(phy_drd->utmiclk)) { - dev_info(phy_drd->dev, - "UTMI phy operational clock not specified\n"); - phy_drd->utmiclk = NULL; - } - - phy_drd->itpclk = devm_clk_get(phy_drd->dev, "itp"); - if (IS_ERR(phy_drd->itpclk)) { - dev_info(phy_drd->dev, - "ITP clock from main OSC not specified\n"); - phy_drd->itpclk = NULL; - } - } - - return 0; -} - static const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = { { .id = EXYNOS5_DRDPHY_UTMI, @@ -615,26 +525,11 @@ static const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = { .phy_cfg = phy_cfg_exynos5, .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL, .pmu_offset_usbdrd1_phy = EXYNOS5420_USBDRD1_PHY_CONTROL, - .has_common_clk_gate = true, }; static const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = { .phy_cfg = phy_cfg_exynos5, .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL, - .has_common_clk_gate = true, -}; - -static const struct exynos5_usbdrd_phy_drvdata exynos5433_usbdrd_phy = { - .phy_cfg = phy_cfg_exynos5, - .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL, - .pmu_offset_usbdrd1_phy = EXYNOS5433_USBHOST30_PHY_CONTROL, - .has_common_clk_gate = false, -}; - -static const struct exynos5_usbdrd_phy_drvdata exynos7_usbdrd_phy = { - .phy_cfg = phy_cfg_exynos5, - .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL, - .has_common_clk_gate = false, }; static const struct of_device_id exynos5_usbdrd_phy_of_match[] = { @@ -644,12 +539,6 @@ static const struct of_device_id exynos5_usbdrd_phy_of_match[] = { }, { .compatible = "samsung,exynos5420-usbdrd-phy", .data = &exynos5420_usbdrd_phy - }, { - .compatible = "samsung,exynos5433-usbdrd-phy", - .data = &exynos5433_usbdrd_phy - }, { - .compatible = "samsung,exynos7-usbdrd-phy", - .data = &exynos7_usbdrd_phy }, { }, }; @@ -666,6 +555,7 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev) const struct exynos5_usbdrd_phy_drvdata *drv_data; struct regmap *reg_pmu; u32 pmu_offset; + unsigned long ref_rate; int i, ret; int channel; @@ -686,9 +576,23 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev) drv_data = match->data; phy_drd->drv_data = drv_data; - ret = exynos5_usbdrd_phy_clk_handle(phy_drd); + phy_drd->clk = devm_clk_get(dev, "phy"); + if (IS_ERR(phy_drd->clk)) { + dev_err(dev, "Failed to get clock of phy controller\n"); + return PTR_ERR(phy_drd->clk); + } + + phy_drd->ref_clk = devm_clk_get(dev, "ref"); + if (IS_ERR(phy_drd->ref_clk)) { + dev_err(dev, "Failed to get reference clock of usbdrd phy\n"); + return PTR_ERR(phy_drd->ref_clk); + } + ref_rate = clk_get_rate(phy_drd->ref_clk); + + ret = exynos5_rate_to_clk(ref_rate, &phy_drd->extrefclk); if (ret) { - dev_err(dev, "Failed to initialize clocks\n"); + dev_err(phy_drd->dev, "Clock rate (%ld) not supported\n", + ref_rate); return ret; } @@ -718,7 +622,7 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev) break; } - /* Get Vbus regulators */ + /* Get Vbus regulator */ phy_drd->vbus = devm_regulator_get(dev, "vbus"); if (IS_ERR(phy_drd->vbus)) { ret = PTR_ERR(phy_drd->vbus); @@ -729,21 +633,12 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev) phy_drd->vbus = NULL; } - phy_drd->vbus_boost = devm_regulator_get(dev, "vbus-boost"); - if (IS_ERR(phy_drd->vbus_boost)) { - ret = PTR_ERR(phy_drd->vbus_boost); - if (ret == -EPROBE_DEFER) - return ret; - - dev_warn(dev, "Failed to get VBUS boost supply regulator\n"); - phy_drd->vbus_boost = NULL; - } - dev_vdbg(dev, "Creating usbdrd_phy phy\n"); for (i = 0; i < EXYNOS5_DRDPHYS_NUM; i++) { struct phy *phy = devm_phy_create(dev, NULL, - &exynos5_usbdrd_phy_ops); + &exynos5_usbdrd_phy_ops, + NULL); if (IS_ERR(phy)) { dev_err(dev, "Failed to create usbdrd_phy phy\n"); return PTR_ERR(phy); diff --git a/drivers/phy/phy-exynos5250-sata.c b/drivers/phy/phy-exynos5250-sata.c index bc858cc800a1..54cf4ae60d29 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) return ret; } - sata_phy->phy = devm_phy_create(dev, NULL, &exynos_sata_phy_ops); + sata_phy->phy = devm_phy_create(dev, NULL, &exynos_sata_phy_ops, NULL); if (IS_ERR(sata_phy->phy)) { clk_disable_unprepare(sata_phy->phyclk); dev_err(dev, "failed to create PHY\n"); diff --git a/drivers/phy/phy-hix5hd2-sata.c b/drivers/phy/phy-hix5hd2-sata.c index 34915b4202f1..d5d978085c6d 100644 --- a/drivers/phy/phy-hix5hd2-sata.c +++ b/drivers/phy/phy-hix5hd2-sata.c @@ -156,7 +156,7 @@ static int hix5hd2_sata_phy_probe(struct platform_device *pdev) if (IS_ERR(priv->peri_ctrl)) priv->peri_ctrl = NULL; - phy = devm_phy_create(dev, NULL, &hix5hd2_sata_phy_ops); + phy = devm_phy_create(dev, NULL, &hix5hd2_sata_phy_ops, NULL); if (IS_ERR(phy)) { dev_err(dev, "failed to create PHY\n"); return PTR_ERR(phy); @@ -164,7 +164,10 @@ static int hix5hd2_sata_phy_probe(struct platform_device *pdev) phy_set_drvdata(phy, priv); phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); - return PTR_ERR_OR_ZERO(phy_provider); + if (IS_ERR(phy_provider)) + return PTR_ERR(phy_provider); + + return 0; } static const struct of_device_id hix5hd2_sata_phy_of_match[] = { diff --git a/drivers/phy/phy-miphy28lp.c b/drivers/phy/phy-miphy28lp.c deleted file mode 100644 index 174ffd037ef7..000000000000 --- a/drivers/phy/phy-miphy28lp.c +++ /dev/null @@ -1,1284 +0,0 @@ -/* - * Copyright (C) 2014 STMicroelectronics - * - * STMicroelectronics PHY driver MiPHY28lp (for SoC STiH407). - * - * Author: Alexandre Torgue - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/* MiPHY registers */ -#define MIPHY_CONF_RESET 0x00 -#define RST_APPLI_SW BIT(0) -#define RST_CONF_SW BIT(1) -#define RST_MACRO_SW BIT(2) - -#define MIPHY_RESET 0x01 -#define RST_PLL_SW BIT(0) -#define RST_COMP_SW BIT(2) - -#define MIPHY_STATUS_1 0x02 -#define PHY_RDY BIT(0) -#define HFC_RDY BIT(1) -#define HFC_PLL BIT(2) - -#define MIPHY_CONTROL 0x04 -#define TERM_EN_SW BIT(2) -#define DIS_LINK_RST BIT(3) -#define AUTO_RST_RX BIT(4) -#define PX_RX_POL BIT(5) - -#define MIPHY_BOUNDARY_SEL 0x0a -#define TX_SEL BIT(6) -#define SSC_SEL BIT(4) -#define GENSEL_SEL BIT(0) - -#define MIPHY_BOUNDARY_1 0x0b -#define MIPHY_BOUNDARY_2 0x0c -#define SSC_EN_SW BIT(2) - -#define MIPHY_PLL_CLKREF_FREQ 0x0d -#define MIPHY_SPEED 0x0e -#define TX_SPDSEL_80DEC 0 -#define TX_SPDSEL_40DEC 1 -#define TX_SPDSEL_20DEC 2 -#define RX_SPDSEL_80DEC 0 -#define RX_SPDSEL_40DEC (1 << 2) -#define RX_SPDSEL_20DEC (2 << 2) - -#define MIPHY_CONF 0x0f -#define MIPHY_CTRL_TEST_SEL 0x20 -#define MIPHY_CTRL_TEST_1 0x21 -#define MIPHY_CTRL_TEST_2 0x22 -#define MIPHY_CTRL_TEST_3 0x23 -#define MIPHY_CTRL_TEST_4 0x24 -#define MIPHY_FEEDBACK_TEST 0x25 -#define MIPHY_DEBUG_BUS 0x26 -#define MIPHY_DEBUG_STATUS_MSB 0x27 -#define MIPHY_DEBUG_STATUS_LSB 0x28 -#define MIPHY_PWR_RAIL_1 0x29 -#define MIPHY_PWR_RAIL_2 0x2a -#define MIPHY_SYNCHAR_CONTROL 0x30 - -#define MIPHY_COMP_FSM_1 0x3a -#define COMP_START BIT(6) - -#define MIPHY_COMP_FSM_6 0x3f -#define COMP_DONE BIT(7) - -#define MIPHY_COMP_POSTP 0x42 -#define MIPHY_TX_CTRL_1 0x49 -#define TX_REG_STEP_0V 0 -#define TX_REG_STEP_P_25MV 1 -#define TX_REG_STEP_P_50MV 2 -#define TX_REG_STEP_N_25MV 7 -#define TX_REG_STEP_N_50MV 6 -#define TX_REG_STEP_N_75MV 5 - -#define MIPHY_TX_CTRL_2 0x4a -#define TX_SLEW_SW_40_PS 0 -#define TX_SLEW_SW_80_PS 1 -#define TX_SLEW_SW_120_PS 2 - -#define MIPHY_TX_CTRL_3 0x4b -#define MIPHY_TX_CAL_MAN 0x4e -#define TX_SLEW_CAL_MAN_EN BIT(0) - -#define MIPHY_TST_BIAS_BOOST_2 0x62 -#define MIPHY_BIAS_BOOST_1 0x63 -#define MIPHY_BIAS_BOOST_2 0x64 -#define MIPHY_RX_DESBUFF_FDB_2 0x67 -#define MIPHY_RX_DESBUFF_FDB_3 0x68 -#define MIPHY_SIGDET_COMPENS1 0x69 -#define MIPHY_SIGDET_COMPENS2 0x6a -#define MIPHY_JITTER_PERIOD 0x6b -#define MIPHY_JITTER_AMPLITUDE_1 0x6c -#define MIPHY_JITTER_AMPLITUDE_2 0x6d -#define MIPHY_JITTER_AMPLITUDE_3 0x6e -#define MIPHY_RX_K_GAIN 0x78 -#define MIPHY_RX_BUFFER_CTRL 0x7a -#define VGA_GAIN BIT(0) -#define EQ_DC_GAIN BIT(2) -#define EQ_BOOST_GAIN BIT(3) - -#define MIPHY_RX_VGA_GAIN 0x7b -#define MIPHY_RX_EQU_GAIN_1 0x7f -#define MIPHY_RX_EQU_GAIN_2 0x80 -#define MIPHY_RX_EQU_GAIN_3 0x81 -#define MIPHY_RX_CAL_CTRL_1 0x97 -#define MIPHY_RX_CAL_CTRL_2 0x98 - -#define MIPHY_RX_CAL_OFFSET_CTRL 0x99 -#define CAL_OFFSET_VGA_64 (0x03 << 0) -#define CAL_OFFSET_THRESHOLD_64 (0x03 << 2) -#define VGA_OFFSET_POLARITY BIT(4) -#define OFFSET_COMPENSATION_EN BIT(6) - -#define MIPHY_RX_CAL_VGA_STEP 0x9a -#define MIPHY_RX_CAL_EYE_MIN 0x9d -#define MIPHY_RX_CAL_OPT_LENGTH 0x9f -#define MIPHY_RX_LOCK_CTRL_1 0xc1 -#define MIPHY_RX_LOCK_SETTINGS_OPT 0xc2 -#define MIPHY_RX_LOCK_STEP 0xc4 - -#define MIPHY_RX_SIGDET_SLEEP_OA 0xc9 -#define MIPHY_RX_SIGDET_SLEEP_SEL 0xca -#define MIPHY_RX_SIGDET_WAIT_SEL 0xcb -#define MIPHY_RX_SIGDET_DATA_SEL 0xcc -#define EN_ULTRA_LOW_POWER BIT(0) -#define EN_FIRST_HALF BIT(1) -#define EN_SECOND_HALF BIT(2) -#define EN_DIGIT_SIGNAL_CHECK BIT(3) - -#define MIPHY_RX_POWER_CTRL_1 0xcd -#define MIPHY_RX_POWER_CTRL_2 0xce -#define MIPHY_PLL_CALSET_CTRL 0xd3 -#define MIPHY_PLL_CALSET_1 0xd4 -#define MIPHY_PLL_CALSET_2 0xd5 -#define MIPHY_PLL_CALSET_3 0xd6 -#define MIPHY_PLL_CALSET_4 0xd7 -#define MIPHY_PLL_SBR_1 0xe3 -#define SET_NEW_CHANGE BIT(1) - -#define MIPHY_PLL_SBR_2 0xe4 -#define MIPHY_PLL_SBR_3 0xe5 -#define MIPHY_PLL_SBR_4 0xe6 -#define MIPHY_PLL_COMMON_MISC_2 0xe9 -#define START_ACT_FILT BIT(6) - -#define MIPHY_PLL_SPAREIN 0xeb - -/* - * On STiH407 the glue logic can be different among MiPHY devices; for example: - * MiPHY0: OSC_FORCE_EXT means: - * 0: 30MHz crystal clk - 1: 100MHz ext clk routed through MiPHY1 - * MiPHY1: OSC_FORCE_EXT means: - * 1: 30MHz crystal clk - 0: 100MHz ext clk routed through MiPHY1 - * Some devices have not the possibility to check if the osc is ready. - */ -#define MIPHY_OSC_FORCE_EXT BIT(3) -#define MIPHY_OSC_RDY BIT(5) - -#define MIPHY_CTRL_MASK 0x0f -#define MIPHY_CTRL_DEFAULT 0 -#define MIPHY_CTRL_SYNC_D_EN BIT(2) - -/* SATA / PCIe defines */ -#define SATA_CTRL_MASK 0x07 -#define PCIE_CTRL_MASK 0xff -#define SATA_CTRL_SELECT_SATA 1 -#define SATA_CTRL_SELECT_PCIE 0 -#define SYSCFG_PCIE_PCIE_VAL 0x80 -#define SATA_SPDMODE 1 - -#define MIPHY_SATA_BANK_NB 3 -#define MIPHY_PCIE_BANK_NB 2 - -enum { - SYSCFG_CTRL, - SYSCFG_STATUS, - SYSCFG_PCI, - SYSCFG_SATA, - SYSCFG_REG_MAX, -}; - -struct miphy28lp_phy { - struct phy *phy; - struct miphy28lp_dev *phydev; - void __iomem *base; - void __iomem *pipebase; - - bool osc_force_ext; - bool osc_rdy; - bool px_rx_pol_inv; - bool ssc; - bool tx_impedance; - - struct reset_control *miphy_rst; - - u32 sata_gen; - - /* Sysconfig registers offsets needed to configure the device */ - u32 syscfg_reg[SYSCFG_REG_MAX]; - u8 type; -}; - -struct miphy28lp_dev { - struct device *dev; - struct regmap *regmap; - struct mutex miphy_mutex; - struct miphy28lp_phy **phys; -}; - -struct miphy_initval { - u16 reg; - u16 val; -}; - -enum miphy_sata_gen { SATA_GEN1, SATA_GEN2, SATA_GEN3 }; - -static char *PHY_TYPE_name[] = { "sata-up", "pcie-up", "", "usb3-up" }; - -struct pll_ratio { - int clk_ref; - int calset_1; - int calset_2; - int calset_3; - int calset_4; - int cal_ctrl; -}; - -static struct pll_ratio sata_pll_ratio = { - .clk_ref = 0x1e, - .calset_1 = 0xc8, - .calset_2 = 0x00, - .calset_3 = 0x00, - .calset_4 = 0x00, - .cal_ctrl = 0x00, -}; - -static struct pll_ratio pcie_pll_ratio = { - .clk_ref = 0x1e, - .calset_1 = 0xa6, - .calset_2 = 0xaa, - .calset_3 = 0xaa, - .calset_4 = 0x00, - .cal_ctrl = 0x00, -}; - -static struct pll_ratio usb3_pll_ratio = { - .clk_ref = 0x1e, - .calset_1 = 0xa6, - .calset_2 = 0xaa, - .calset_3 = 0xaa, - .calset_4 = 0x04, - .cal_ctrl = 0x00, -}; - -struct miphy28lp_pll_gen { - int bank; - int speed; - int bias_boost_1; - int bias_boost_2; - int tx_ctrl_1; - int tx_ctrl_2; - int tx_ctrl_3; - int rx_k_gain; - int rx_vga_gain; - int rx_equ_gain_1; - int rx_equ_gain_2; - int rx_equ_gain_3; - int rx_buff_ctrl; -}; - -static struct miphy28lp_pll_gen sata_pll_gen[] = { - { - .bank = 0x00, - .speed = TX_SPDSEL_80DEC | RX_SPDSEL_80DEC, - .bias_boost_1 = 0x00, - .bias_boost_2 = 0xae, - .tx_ctrl_2 = 0x53, - .tx_ctrl_3 = 0x00, - .rx_buff_ctrl = EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN, - .rx_vga_gain = 0x00, - .rx_equ_gain_1 = 0x7d, - .rx_equ_gain_2 = 0x56, - .rx_equ_gain_3 = 0x00, - }, - { - .bank = 0x01, - .speed = TX_SPDSEL_40DEC | RX_SPDSEL_40DEC, - .bias_boost_1 = 0x00, - .bias_boost_2 = 0xae, - .tx_ctrl_2 = 0x72, - .tx_ctrl_3 = 0x20, - .rx_buff_ctrl = EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN, - .rx_vga_gain = 0x00, - .rx_equ_gain_1 = 0x7d, - .rx_equ_gain_2 = 0x56, - .rx_equ_gain_3 = 0x00, - }, - { - .bank = 0x02, - .speed = TX_SPDSEL_20DEC | RX_SPDSEL_20DEC, - .bias_boost_1 = 0x00, - .bias_boost_2 = 0xae, - .tx_ctrl_2 = 0xc0, - .tx_ctrl_3 = 0x20, - .rx_buff_ctrl = EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN, - .rx_vga_gain = 0x00, - .rx_equ_gain_1 = 0x7d, - .rx_equ_gain_2 = 0x56, - .rx_equ_gain_3 = 0x00, - }, -}; - -static struct miphy28lp_pll_gen pcie_pll_gen[] = { - { - .bank = 0x00, - .speed = TX_SPDSEL_40DEC | RX_SPDSEL_40DEC, - .bias_boost_1 = 0x00, - .bias_boost_2 = 0xa5, - .tx_ctrl_1 = TX_REG_STEP_N_25MV, - .tx_ctrl_2 = 0x71, - .tx_ctrl_3 = 0x60, - .rx_k_gain = 0x98, - .rx_buff_ctrl = EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN, - .rx_vga_gain = 0x00, - .rx_equ_gain_1 = 0x79, - .rx_equ_gain_2 = 0x56, - }, - { - .bank = 0x01, - .speed = TX_SPDSEL_20DEC | RX_SPDSEL_20DEC, - .bias_boost_1 = 0x00, - .bias_boost_2 = 0xa5, - .tx_ctrl_1 = TX_REG_STEP_N_25MV, - .tx_ctrl_2 = 0x70, - .tx_ctrl_3 = 0x60, - .rx_k_gain = 0xcc, - .rx_buff_ctrl = EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN, - .rx_vga_gain = 0x00, - .rx_equ_gain_1 = 0x78, - .rx_equ_gain_2 = 0x07, - }, -}; - -static inline void miphy28lp_set_reset(struct miphy28lp_phy *miphy_phy) -{ - void *base = miphy_phy->base; - u8 val; - - /* Putting Macro in reset */ - writeb_relaxed(RST_APPLI_SW, base + MIPHY_CONF_RESET); - - val = RST_APPLI_SW | RST_CONF_SW; - writeb_relaxed(val, base + MIPHY_CONF_RESET); - - writeb_relaxed(RST_APPLI_SW, base + MIPHY_CONF_RESET); - - /* Bringing the MIPHY-CPU registers out of reset */ - if (miphy_phy->type == PHY_TYPE_PCIE) { - val = AUTO_RST_RX | TERM_EN_SW; - writeb_relaxed(val, base + MIPHY_CONTROL); - } else { - val = AUTO_RST_RX | TERM_EN_SW | DIS_LINK_RST; - writeb_relaxed(val, base + MIPHY_CONTROL); - } -} - -static inline void miphy28lp_pll_calibration(struct miphy28lp_phy *miphy_phy, - struct pll_ratio *pll_ratio) -{ - void *base = miphy_phy->base; - u8 val; - - /* Applying PLL Settings */ - writeb_relaxed(0x1d, base + MIPHY_PLL_SPAREIN); - writeb_relaxed(pll_ratio->clk_ref, base + MIPHY_PLL_CLKREF_FREQ); - - /* PLL Ratio */ - writeb_relaxed(pll_ratio->calset_1, base + MIPHY_PLL_CALSET_1); - writeb_relaxed(pll_ratio->calset_2, base + MIPHY_PLL_CALSET_2); - writeb_relaxed(pll_ratio->calset_3, base + MIPHY_PLL_CALSET_3); - writeb_relaxed(pll_ratio->calset_4, base + MIPHY_PLL_CALSET_4); - writeb_relaxed(pll_ratio->cal_ctrl, base + MIPHY_PLL_CALSET_CTRL); - - writeb_relaxed(TX_SEL, base + MIPHY_BOUNDARY_SEL); - - val = (0x68 << 1) | TX_SLEW_CAL_MAN_EN; - writeb_relaxed(val, base + MIPHY_TX_CAL_MAN); - - val = VGA_OFFSET_POLARITY | CAL_OFFSET_THRESHOLD_64 | CAL_OFFSET_VGA_64; - - if (miphy_phy->type != PHY_TYPE_SATA) - val |= OFFSET_COMPENSATION_EN; - - writeb_relaxed(val, base + MIPHY_RX_CAL_OFFSET_CTRL); - - if (miphy_phy->type == PHY_TYPE_USB3) { - writeb_relaxed(0x00, base + MIPHY_CONF); - writeb_relaxed(0x70, base + MIPHY_RX_LOCK_STEP); - writeb_relaxed(EN_FIRST_HALF, base + MIPHY_RX_SIGDET_SLEEP_OA); - writeb_relaxed(EN_FIRST_HALF, base + MIPHY_RX_SIGDET_SLEEP_SEL); - writeb_relaxed(EN_FIRST_HALF, base + MIPHY_RX_SIGDET_WAIT_SEL); - - val = EN_DIGIT_SIGNAL_CHECK | EN_FIRST_HALF; - writeb_relaxed(val, base + MIPHY_RX_SIGDET_DATA_SEL); - } - -} - -static inline void miphy28lp_sata_config_gen(struct miphy28lp_phy *miphy_phy) -{ - void __iomem *base = miphy_phy->base; - int i; - - for (i = 0; i < ARRAY_SIZE(sata_pll_gen); i++) { - struct miphy28lp_pll_gen *gen = &sata_pll_gen[i]; - - /* Banked settings */ - writeb_relaxed(gen->bank, base + MIPHY_CONF); - writeb_relaxed(gen->speed, base + MIPHY_SPEED); - writeb_relaxed(gen->bias_boost_1, base + MIPHY_BIAS_BOOST_1); - writeb_relaxed(gen->bias_boost_2, base + MIPHY_BIAS_BOOST_2); - - /* TX buffer Settings */ - writeb_relaxed(gen->tx_ctrl_2, base + MIPHY_TX_CTRL_2); - writeb_relaxed(gen->tx_ctrl_3, base + MIPHY_TX_CTRL_3); - - /* RX Buffer Settings */ - writeb_relaxed(gen->rx_buff_ctrl, base + MIPHY_RX_BUFFER_CTRL); - writeb_relaxed(gen->rx_vga_gain, base + MIPHY_RX_VGA_GAIN); - writeb_relaxed(gen->rx_equ_gain_1, base + MIPHY_RX_EQU_GAIN_1); - writeb_relaxed(gen->rx_equ_gain_2, base + MIPHY_RX_EQU_GAIN_2); - writeb_relaxed(gen->rx_equ_gain_3, base + MIPHY_RX_EQU_GAIN_3); - } -} - -static inline void miphy28lp_pcie_config_gen(struct miphy28lp_phy *miphy_phy) -{ - void __iomem *base = miphy_phy->base; - int i; - - for (i = 0; i < ARRAY_SIZE(pcie_pll_gen); i++) { - struct miphy28lp_pll_gen *gen = &pcie_pll_gen[i]; - - /* Banked settings */ - writeb_relaxed(gen->bank, base + MIPHY_CONF); - writeb_relaxed(gen->speed, base + MIPHY_SPEED); - writeb_relaxed(gen->bias_boost_1, base + MIPHY_BIAS_BOOST_1); - writeb_relaxed(gen->bias_boost_2, base + MIPHY_BIAS_BOOST_2); - - /* TX buffer Settings */ - writeb_relaxed(gen->tx_ctrl_1, base + MIPHY_TX_CTRL_1); - writeb_relaxed(gen->tx_ctrl_2, base + MIPHY_TX_CTRL_2); - writeb_relaxed(gen->tx_ctrl_3, base + MIPHY_TX_CTRL_3); - - writeb_relaxed(gen->rx_k_gain, base + MIPHY_RX_K_GAIN); - - /* RX Buffer Settings */ - writeb_relaxed(gen->rx_buff_ctrl, base + MIPHY_RX_BUFFER_CTRL); - writeb_relaxed(gen->rx_vga_gain, base + MIPHY_RX_VGA_GAIN); - writeb_relaxed(gen->rx_equ_gain_1, base + MIPHY_RX_EQU_GAIN_1); - writeb_relaxed(gen->rx_equ_gain_2, base + MIPHY_RX_EQU_GAIN_2); - } -} - -static inline int miphy28lp_wait_compensation(struct miphy28lp_phy *miphy_phy) -{ - unsigned long finish = jiffies + 5 * HZ; - u8 val; - - /* Waiting for Compensation to complete */ - do { - val = readb_relaxed(miphy_phy->base + MIPHY_COMP_FSM_6); - - if (time_after_eq(jiffies, finish)) - return -EBUSY; - cpu_relax(); - } while (!(val & COMP_DONE)); - - return 0; -} - - -static inline int miphy28lp_compensation(struct miphy28lp_phy *miphy_phy, - struct pll_ratio *pll_ratio) -{ - void __iomem *base = miphy_phy->base; - - /* Poll for HFC ready after reset release */ - /* Compensation measurement */ - writeb_relaxed(RST_PLL_SW | RST_COMP_SW, base + MIPHY_RESET); - - writeb_relaxed(0x00, base + MIPHY_PLL_COMMON_MISC_2); - writeb_relaxed(pll_ratio->clk_ref, base + MIPHY_PLL_CLKREF_FREQ); - writeb_relaxed(COMP_START, base + MIPHY_COMP_FSM_1); - - if (miphy_phy->type == PHY_TYPE_PCIE) - writeb_relaxed(RST_PLL_SW, base + MIPHY_RESET); - - writeb_relaxed(0x00, base + MIPHY_RESET); - writeb_relaxed(START_ACT_FILT, base + MIPHY_PLL_COMMON_MISC_2); - writeb_relaxed(SET_NEW_CHANGE, base + MIPHY_PLL_SBR_1); - - /* TX compensation offset to re-center TX impedance */ - writeb_relaxed(0x00, base + MIPHY_COMP_POSTP); - - if (miphy_phy->type == PHY_TYPE_PCIE) - return miphy28lp_wait_compensation(miphy_phy); - - return 0; -} - -static inline void miphy28_usb3_miphy_reset(struct miphy28lp_phy *miphy_phy) -{ - void __iomem *base = miphy_phy->base; - u8 val; - - /* MIPHY Reset */ - writeb_relaxed(RST_APPLI_SW, base + MIPHY_CONF_RESET); - writeb_relaxed(0x00, base + MIPHY_CONF_RESET); - writeb_relaxed(RST_COMP_SW, base + MIPHY_RESET); - - val = RST_COMP_SW | RST_PLL_SW; - writeb_relaxed(val, base + MIPHY_RESET); - - writeb_relaxed(0x00, base + MIPHY_PLL_COMMON_MISC_2); - writeb_relaxed(0x1e, base + MIPHY_PLL_CLKREF_FREQ); - writeb_relaxed(COMP_START, base + MIPHY_COMP_FSM_1); - writeb_relaxed(RST_PLL_SW, base + MIPHY_RESET); - writeb_relaxed(0x00, base + MIPHY_RESET); - writeb_relaxed(START_ACT_FILT, base + MIPHY_PLL_COMMON_MISC_2); - writeb_relaxed(0x00, base + MIPHY_CONF); - writeb_relaxed(0x00, base + MIPHY_BOUNDARY_1); - writeb_relaxed(0x00, base + MIPHY_TST_BIAS_BOOST_2); - writeb_relaxed(0x00, base + MIPHY_CONF); - writeb_relaxed(SET_NEW_CHANGE, base + MIPHY_PLL_SBR_1); - writeb_relaxed(0xa5, base + MIPHY_DEBUG_BUS); - writeb_relaxed(0x00, base + MIPHY_CONF); -} - -static void miphy_sata_tune_ssc(struct miphy28lp_phy *miphy_phy) -{ - void __iomem *base = miphy_phy->base; - u8 val; - - /* Compensate Tx impedance to avoid out of range values */ - /* - * Enable the SSC on PLL for all banks - * SSC Modulation @ 31 KHz and 4000 ppm modulation amp - */ - val = readb_relaxed(base + MIPHY_BOUNDARY_2); - val |= SSC_EN_SW; - writeb_relaxed(val, base + MIPHY_BOUNDARY_2); - - val = readb_relaxed(base + MIPHY_BOUNDARY_SEL); - val |= SSC_SEL; - writeb_relaxed(val, base + MIPHY_BOUNDARY_SEL); - - for (val = 0; val < MIPHY_SATA_BANK_NB; val++) { - writeb_relaxed(val, base + MIPHY_CONF); - - /* Add value to each reference clock cycle */ - /* and define the period length of the SSC */ - writeb_relaxed(0x3c, base + MIPHY_PLL_SBR_2); - writeb_relaxed(0x6c, base + MIPHY_PLL_SBR_3); - writeb_relaxed(0x81, base + MIPHY_PLL_SBR_4); - - /* Clear any previous request */ - writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1); - - /* requests the PLL to take in account new parameters */ - writeb_relaxed(SET_NEW_CHANGE, base + MIPHY_PLL_SBR_1); - - /* To be sure there is no other pending requests */ - writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1); - } -} - -static void miphy_pcie_tune_ssc(struct miphy28lp_phy *miphy_phy) -{ - void __iomem *base = miphy_phy->base; - u8 val; - - /* Compensate Tx impedance to avoid out of range values */ - /* - * Enable the SSC on PLL for all banks - * SSC Modulation @ 31 KHz and 4000 ppm modulation amp - */ - val = readb_relaxed(base + MIPHY_BOUNDARY_2); - val |= SSC_EN_SW; - writeb_relaxed(val, base + MIPHY_BOUNDARY_2); - - val = readb_relaxed(base + MIPHY_BOUNDARY_SEL); - val |= SSC_SEL; - writeb_relaxed(val, base + MIPHY_BOUNDARY_SEL); - - for (val = 0; val < MIPHY_PCIE_BANK_NB; val++) { - writeb_relaxed(val, base + MIPHY_CONF); - - /* Validate Step component */ - writeb_relaxed(0x69, base + MIPHY_PLL_SBR_3); - writeb_relaxed(0x21, base + MIPHY_PLL_SBR_4); - - /* Validate Period component */ - writeb_relaxed(0x3c, base + MIPHY_PLL_SBR_2); - writeb_relaxed(0x21, base + MIPHY_PLL_SBR_4); - - /* Clear any previous request */ - writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1); - - /* requests the PLL to take in account new parameters */ - writeb_relaxed(SET_NEW_CHANGE, base + MIPHY_PLL_SBR_1); - - /* To be sure there is no other pending requests */ - writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1); - } -} - -static inline void miphy_tune_tx_impedance(struct miphy28lp_phy *miphy_phy) -{ - /* Compensate Tx impedance to avoid out of range values */ - writeb_relaxed(0x02, miphy_phy->base + MIPHY_COMP_POSTP); -} - -static inline int miphy28lp_configure_sata(struct miphy28lp_phy *miphy_phy) -{ - void __iomem *base = miphy_phy->base; - int err; - u8 val; - - /* Putting Macro in reset */ - miphy28lp_set_reset(miphy_phy); - - /* PLL calibration */ - miphy28lp_pll_calibration(miphy_phy, &sata_pll_ratio); - - /* Banked settings Gen1/Gen2/Gen3 */ - miphy28lp_sata_config_gen(miphy_phy); - - /* Power control */ - /* Input bridge enable, manual input bridge control */ - writeb_relaxed(0x21, base + MIPHY_RX_POWER_CTRL_1); - - /* Macro out of reset */ - writeb_relaxed(0x00, base + MIPHY_CONF_RESET); - - /* Poll for HFC ready after reset release */ - /* Compensation measurement */ - err = miphy28lp_compensation(miphy_phy, &sata_pll_ratio); - if (err) - return err; - - if (miphy_phy->px_rx_pol_inv) { - /* Invert Rx polarity */ - val = readb_relaxed(miphy_phy->base + MIPHY_CONTROL); - val |= PX_RX_POL; - writeb_relaxed(val, miphy_phy->base + MIPHY_CONTROL); - } - - if (miphy_phy->ssc) - miphy_sata_tune_ssc(miphy_phy); - - if (miphy_phy->tx_impedance) - miphy_tune_tx_impedance(miphy_phy); - - return 0; -} - -static inline int miphy28lp_configure_pcie(struct miphy28lp_phy *miphy_phy) -{ - void __iomem *base = miphy_phy->base; - int err; - - /* Putting Macro in reset */ - miphy28lp_set_reset(miphy_phy); - - /* PLL calibration */ - miphy28lp_pll_calibration(miphy_phy, &pcie_pll_ratio); - - /* Banked settings Gen1/Gen2 */ - miphy28lp_pcie_config_gen(miphy_phy); - - /* Power control */ - /* Input bridge enable, manual input bridge control */ - writeb_relaxed(0x21, base + MIPHY_RX_POWER_CTRL_1); - - /* Macro out of reset */ - writeb_relaxed(0x00, base + MIPHY_CONF_RESET); - - /* Poll for HFC ready after reset release */ - /* Compensation measurement */ - err = miphy28lp_compensation(miphy_phy, &pcie_pll_ratio); - if (err) - return err; - - if (miphy_phy->ssc) - miphy_pcie_tune_ssc(miphy_phy); - - if (miphy_phy->tx_impedance) - miphy_tune_tx_impedance(miphy_phy); - - return 0; -} - - -static inline void miphy28lp_configure_usb3(struct miphy28lp_phy *miphy_phy) -{ - void __iomem *base = miphy_phy->base; - u8 val; - - /* Putting Macro in reset */ - miphy28lp_set_reset(miphy_phy); - - /* PLL calibration */ - miphy28lp_pll_calibration(miphy_phy, &usb3_pll_ratio); - - /* Writing The Speed Rate */ - writeb_relaxed(0x00, base + MIPHY_CONF); - - val = RX_SPDSEL_20DEC | TX_SPDSEL_20DEC; - writeb_relaxed(val, base + MIPHY_SPEED); - - /* RX Channel compensation and calibration */ - writeb_relaxed(0x1c, base + MIPHY_RX_LOCK_SETTINGS_OPT); - writeb_relaxed(0x51, base + MIPHY_RX_CAL_CTRL_1); - writeb_relaxed(0x70, base + MIPHY_RX_CAL_CTRL_2); - - val = OFFSET_COMPENSATION_EN | VGA_OFFSET_POLARITY | - CAL_OFFSET_THRESHOLD_64 | CAL_OFFSET_VGA_64; - writeb_relaxed(val, base + MIPHY_RX_CAL_OFFSET_CTRL); - writeb_relaxed(0x22, base + MIPHY_RX_CAL_VGA_STEP); - writeb_relaxed(0x0e, base + MIPHY_RX_CAL_OPT_LENGTH); - - val = EQ_DC_GAIN | VGA_GAIN; - writeb_relaxed(val, base + MIPHY_RX_BUFFER_CTRL); - writeb_relaxed(0x78, base + MIPHY_RX_EQU_GAIN_1); - writeb_relaxed(0x1b, base + MIPHY_SYNCHAR_CONTROL); - - /* TX compensation offset to re-center TX impedance */ - writeb_relaxed(0x02, base + MIPHY_COMP_POSTP); - - /* Enable GENSEL_SEL and SSC */ - /* TX_SEL=0 swing preemp forced by pipe registres */ - val = SSC_SEL | GENSEL_SEL; - writeb_relaxed(val, base + MIPHY_BOUNDARY_SEL); - - /* MIPHY Bias boost */ - writeb_relaxed(0x00, base + MIPHY_BIAS_BOOST_1); - writeb_relaxed(0xa7, base + MIPHY_BIAS_BOOST_2); - - /* SSC modulation */ - writeb_relaxed(SSC_EN_SW, base + MIPHY_BOUNDARY_2); - - /* MIPHY TX control */ - writeb_relaxed(0x00, base + MIPHY_CONF); - - /* Validate Step component */ - writeb_relaxed(0x5a, base + MIPHY_PLL_SBR_3); - writeb_relaxed(0xa0, base + MIPHY_PLL_SBR_4); - - /* Validate Period component */ - writeb_relaxed(0x3c, base + MIPHY_PLL_SBR_2); - writeb_relaxed(0xa1, base + MIPHY_PLL_SBR_4); - - /* Clear any previous request */ - writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1); - - /* requests the PLL to take in account new parameters */ - writeb_relaxed(0x02, base + MIPHY_PLL_SBR_1); - - /* To be sure there is no other pending requests */ - writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1); - - /* Rx PI controller settings */ - writeb_relaxed(0xca, base + MIPHY_RX_K_GAIN); - - /* MIPHY RX input bridge control */ - /* INPUT_BRIDGE_EN_SW=1, manual input bridge control[0]=1 */ - writeb_relaxed(0x21, base + MIPHY_RX_POWER_CTRL_1); - writeb_relaxed(0x29, base + MIPHY_RX_POWER_CTRL_1); - writeb_relaxed(0x1a, base + MIPHY_RX_POWER_CTRL_2); - - /* MIPHY Reset for usb3 */ - miphy28_usb3_miphy_reset(miphy_phy); -} - -static inline int miphy_is_ready(struct miphy28lp_phy *miphy_phy) -{ - unsigned long finish = jiffies + 5 * HZ; - u8 mask = HFC_PLL | HFC_RDY; - u8 val; - - /* - * For PCIe and USB3 check only that PLL and HFC are ready - * For SATA check also that phy is ready! - */ - if (miphy_phy->type == PHY_TYPE_SATA) - mask |= PHY_RDY; - - do { - val = readb_relaxed(miphy_phy->base + MIPHY_STATUS_1); - if ((val & mask) != mask) - cpu_relax(); - else - return 0; - } while (!time_after_eq(jiffies, finish)); - - return -EBUSY; -} - -static int miphy_osc_is_ready(struct miphy28lp_phy *miphy_phy) -{ - struct miphy28lp_dev *miphy_dev = miphy_phy->phydev; - unsigned long finish = jiffies + 5 * HZ; - u32 val; - - if (!miphy_phy->osc_rdy) - return 0; - - if (!miphy_phy->syscfg_reg[SYSCFG_STATUS]) - return -EINVAL; - - do { - regmap_read(miphy_dev->regmap, - miphy_phy->syscfg_reg[SYSCFG_STATUS], &val); - - if ((val & MIPHY_OSC_RDY) != MIPHY_OSC_RDY) - cpu_relax(); - else - return 0; - } while (!time_after_eq(jiffies, finish)); - - return -EBUSY; -} - -static int miphy28lp_get_resource_byname(struct device_node *child, - char *rname, struct resource *res) -{ - int index; - - index = of_property_match_string(child, "reg-names", rname); - if (index < 0) - return -ENODEV; - - return of_address_to_resource(child, index, res); -} - -static int miphy28lp_get_one_addr(struct device *dev, - struct device_node *child, char *rname, - void __iomem **base) -{ - struct resource res; - int ret; - - ret = miphy28lp_get_resource_byname(child, rname, &res); - if (!ret) { - *base = devm_ioremap(dev, res.start, resource_size(&res)); - if (!*base) { - dev_err(dev, "failed to ioremap %s address region\n" - , rname); - return -ENOENT; - } - } - - return 0; -} - -/* MiPHY reset and sysconf setup */ -static int miphy28lp_setup(struct miphy28lp_phy *miphy_phy, u32 miphy_val) -{ - int err; - struct miphy28lp_dev *miphy_dev = miphy_phy->phydev; - - if (!miphy_phy->syscfg_reg[SYSCFG_CTRL]) - return -EINVAL; - - err = reset_control_assert(miphy_phy->miphy_rst); - if (err) { - dev_err(miphy_dev->dev, "unable to bring out of miphy reset\n"); - return err; - } - - if (miphy_phy->osc_force_ext) - miphy_val |= MIPHY_OSC_FORCE_EXT; - - regmap_update_bits(miphy_dev->regmap, - miphy_phy->syscfg_reg[SYSCFG_CTRL], - MIPHY_CTRL_MASK, miphy_val); - - err = reset_control_deassert(miphy_phy->miphy_rst); - if (err) { - dev_err(miphy_dev->dev, "unable to bring out of miphy reset\n"); - return err; - } - - return miphy_osc_is_ready(miphy_phy); -} - -static int miphy28lp_init_sata(struct miphy28lp_phy *miphy_phy) -{ - struct miphy28lp_dev *miphy_dev = miphy_phy->phydev; - int err, sata_conf = SATA_CTRL_SELECT_SATA; - - if ((!miphy_phy->syscfg_reg[SYSCFG_SATA]) || - (!miphy_phy->syscfg_reg[SYSCFG_PCI]) || - (!miphy_phy->base)) - return -EINVAL; - - dev_info(miphy_dev->dev, "sata-up mode, addr 0x%p\n", miphy_phy->base); - - /* Configure the glue-logic */ - sata_conf |= ((miphy_phy->sata_gen - SATA_GEN1) << SATA_SPDMODE); - - regmap_update_bits(miphy_dev->regmap, - miphy_phy->syscfg_reg[SYSCFG_SATA], - SATA_CTRL_MASK, sata_conf); - - regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_reg[SYSCFG_PCI], - PCIE_CTRL_MASK, SATA_CTRL_SELECT_PCIE); - - /* MiPHY path and clocking init */ - err = miphy28lp_setup(miphy_phy, MIPHY_CTRL_DEFAULT); - - if (err) { - dev_err(miphy_dev->dev, "SATA phy setup failed\n"); - return err; - } - - /* initialize miphy */ - miphy28lp_configure_sata(miphy_phy); - - return miphy_is_ready(miphy_phy); -} - -static int miphy28lp_init_pcie(struct miphy28lp_phy *miphy_phy) -{ - struct miphy28lp_dev *miphy_dev = miphy_phy->phydev; - int err; - - if ((!miphy_phy->syscfg_reg[SYSCFG_SATA]) || - (!miphy_phy->syscfg_reg[SYSCFG_PCI]) - || (!miphy_phy->base) || (!miphy_phy->pipebase)) - return -EINVAL; - - dev_info(miphy_dev->dev, "pcie-up mode, addr 0x%p\n", miphy_phy->base); - - /* Configure the glue-logic */ - regmap_update_bits(miphy_dev->regmap, - miphy_phy->syscfg_reg[SYSCFG_SATA], - SATA_CTRL_MASK, SATA_CTRL_SELECT_PCIE); - - regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_reg[SYSCFG_PCI], - PCIE_CTRL_MASK, SYSCFG_PCIE_PCIE_VAL); - - /* MiPHY path and clocking init */ - err = miphy28lp_setup(miphy_phy, MIPHY_CTRL_DEFAULT); - - if (err) { - dev_err(miphy_dev->dev, "PCIe phy setup failed\n"); - return err; - } - - /* initialize miphy */ - err = miphy28lp_configure_pcie(miphy_phy); - if (err) - return err; - - /* PIPE Wrapper Configuration */ - writeb_relaxed(0x68, miphy_phy->pipebase + 0x104); /* Rise_0 */ - writeb_relaxed(0x61, miphy_phy->pipebase + 0x105); /* Rise_1 */ - writeb_relaxed(0x68, miphy_phy->pipebase + 0x108); /* Fall_0 */ - writeb_relaxed(0x61, miphy_phy->pipebase + 0x109); /* Fall-1 */ - writeb_relaxed(0x68, miphy_phy->pipebase + 0x10c); /* Threshold_0 */ - writeb_relaxed(0x60, miphy_phy->pipebase + 0x10d); /* Threshold_1 */ - - /* Wait for phy_ready */ - return miphy_is_ready(miphy_phy); -} - -static int miphy28lp_init_usb3(struct miphy28lp_phy *miphy_phy) -{ - struct miphy28lp_dev *miphy_dev = miphy_phy->phydev; - int err; - - if ((!miphy_phy->base) || (!miphy_phy->pipebase)) - return -EINVAL; - - dev_info(miphy_dev->dev, "usb3-up mode, addr 0x%p\n", miphy_phy->base); - - /* MiPHY path and clocking init */ - err = miphy28lp_setup(miphy_phy, MIPHY_CTRL_SYNC_D_EN); - if (err) { - dev_err(miphy_dev->dev, "USB3 phy setup failed\n"); - return err; - } - - /* initialize miphy */ - miphy28lp_configure_usb3(miphy_phy); - - /* PIPE Wrapper Configuration */ - writeb_relaxed(0x68, miphy_phy->pipebase + 0x23); - writeb_relaxed(0x61, miphy_phy->pipebase + 0x24); - writeb_relaxed(0x68, miphy_phy->pipebase + 0x26); - writeb_relaxed(0x61, miphy_phy->pipebase + 0x27); - writeb_relaxed(0x18, miphy_phy->pipebase + 0x29); - writeb_relaxed(0x61, miphy_phy->pipebase + 0x2a); - - /* pipe Wrapper usb3 TX swing de-emph margin PREEMPH[7:4], SWING[3:0] */ - writeb_relaxed(0X67, miphy_phy->pipebase + 0x68); - writeb_relaxed(0x0d, miphy_phy->pipebase + 0x69); - writeb_relaxed(0X67, miphy_phy->pipebase + 0x6a); - writeb_relaxed(0X0d, miphy_phy->pipebase + 0x6b); - writeb_relaxed(0X67, miphy_phy->pipebase + 0x6c); - writeb_relaxed(0X0d, miphy_phy->pipebase + 0x6d); - writeb_relaxed(0X67, miphy_phy->pipebase + 0x6e); - writeb_relaxed(0X0d, miphy_phy->pipebase + 0x6f); - - return miphy_is_ready(miphy_phy); -} - -static int miphy28lp_init(struct phy *phy) -{ - struct miphy28lp_phy *miphy_phy = phy_get_drvdata(phy); - struct miphy28lp_dev *miphy_dev = miphy_phy->phydev; - int ret; - - mutex_lock(&miphy_dev->miphy_mutex); - - switch (miphy_phy->type) { - - case PHY_TYPE_SATA: - ret = miphy28lp_init_sata(miphy_phy); - break; - case PHY_TYPE_PCIE: - ret = miphy28lp_init_pcie(miphy_phy); - break; - case PHY_TYPE_USB3: - ret = miphy28lp_init_usb3(miphy_phy); - break; - default: - ret = -EINVAL; - break; - } - - mutex_unlock(&miphy_dev->miphy_mutex); - - return ret; -} - -static int miphy28lp_get_addr(struct miphy28lp_phy *miphy_phy) -{ - struct miphy28lp_dev *miphy_dev = miphy_phy->phydev; - struct device_node *phynode = miphy_phy->phy->dev.of_node; - int err; - - if ((miphy_phy->type != PHY_TYPE_SATA) && - (miphy_phy->type != PHY_TYPE_PCIE) && - (miphy_phy->type != PHY_TYPE_USB3)) { - return -EINVAL; - } - - err = miphy28lp_get_one_addr(miphy_dev->dev, phynode, - PHY_TYPE_name[miphy_phy->type - PHY_TYPE_SATA], - &miphy_phy->base); - if (err) - return err; - - if ((miphy_phy->type == PHY_TYPE_PCIE) || - (miphy_phy->type == PHY_TYPE_USB3)) { - err = miphy28lp_get_one_addr(miphy_dev->dev, phynode, "pipew", - &miphy_phy->pipebase); - if (err) - return err; - } - - return 0; -} - -static struct phy *miphy28lp_xlate(struct device *dev, - struct of_phandle_args *args) -{ - struct miphy28lp_dev *miphy_dev = dev_get_drvdata(dev); - struct miphy28lp_phy *miphy_phy = NULL; - struct device_node *phynode = args->np; - int ret, index = 0; - - if (!of_device_is_available(phynode)) { - dev_warn(dev, "Requested PHY is disabled\n"); - return ERR_PTR(-ENODEV); - } - - if (args->args_count != 1) { - dev_err(dev, "Invalid number of cells in 'phy' property\n"); - return ERR_PTR(-EINVAL); - } - - for (index = 0; index < of_get_child_count(dev->of_node); index++) - if (phynode == miphy_dev->phys[index]->phy->dev.of_node) { - miphy_phy = miphy_dev->phys[index]; - break; - } - - if (!miphy_phy) { - dev_err(dev, "Failed to find appropriate phy\n"); - return ERR_PTR(-EINVAL); - } - - miphy_phy->type = args->args[0]; - - ret = miphy28lp_get_addr(miphy_phy); - if (ret < 0) - return ERR_PTR(ret); - - return miphy_phy->phy; -} - -static struct phy_ops miphy28lp_ops = { - .init = miphy28lp_init, -}; - -static int miphy28lp_probe_resets(struct device_node *node, - struct miphy28lp_phy *miphy_phy) -{ - struct miphy28lp_dev *miphy_dev = miphy_phy->phydev; - int err; - - miphy_phy->miphy_rst = of_reset_control_get(node, "miphy-sw-rst"); - - if (IS_ERR(miphy_phy->miphy_rst)) { - dev_err(miphy_dev->dev, - "miphy soft reset control not defined\n"); - return PTR_ERR(miphy_phy->miphy_rst); - } - - err = reset_control_deassert(miphy_phy->miphy_rst); - if (err) { - dev_err(miphy_dev->dev, "unable to bring out of miphy reset\n"); - return err; - } - - return 0; -} - -static int miphy28lp_of_probe(struct device_node *np, - struct miphy28lp_phy *miphy_phy) -{ - int i; - u32 ctrlreg; - - miphy_phy->osc_force_ext = - of_property_read_bool(np, "st,osc-force-ext"); - - miphy_phy->osc_rdy = of_property_read_bool(np, "st,osc-rdy"); - - miphy_phy->px_rx_pol_inv = - of_property_read_bool(np, "st,px_rx_pol_inv"); - - miphy_phy->ssc = of_property_read_bool(np, "st,ssc-on"); - - miphy_phy->tx_impedance = - of_property_read_bool(np, "st,tx-impedance-comp"); - - of_property_read_u32(np, "st,sata-gen", &miphy_phy->sata_gen); - if (!miphy_phy->sata_gen) - miphy_phy->sata_gen = SATA_GEN1; - - for (i = 0; i < SYSCFG_REG_MAX; i++) { - if (!of_property_read_u32_index(np, "st,syscfg", i, &ctrlreg)) - miphy_phy->syscfg_reg[i] = ctrlreg; - } - - return 0; -} - -static int miphy28lp_probe(struct platform_device *pdev) -{ - struct device_node *child, *np = pdev->dev.of_node; - struct miphy28lp_dev *miphy_dev; - struct phy_provider *provider; - struct phy *phy; - int chancount, port = 0; - int ret; - - miphy_dev = devm_kzalloc(&pdev->dev, sizeof(*miphy_dev), GFP_KERNEL); - if (!miphy_dev) - return -ENOMEM; - - chancount = of_get_child_count(np); - miphy_dev->phys = devm_kzalloc(&pdev->dev, sizeof(phy) * chancount, - GFP_KERNEL); - if (!miphy_dev->phys) - return -ENOMEM; - - miphy_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); - if (IS_ERR(miphy_dev->regmap)) { - dev_err(miphy_dev->dev, "No syscfg phandle specified\n"); - return PTR_ERR(miphy_dev->regmap); - } - - miphy_dev->dev = &pdev->dev; - - dev_set_drvdata(&pdev->dev, miphy_dev); - - mutex_init(&miphy_dev->miphy_mutex); - - for_each_child_of_node(np, child) { - struct miphy28lp_phy *miphy_phy; - - miphy_phy = devm_kzalloc(&pdev->dev, sizeof(*miphy_phy), - GFP_KERNEL); - if (!miphy_phy) - return -ENOMEM; - - miphy_dev->phys[port] = miphy_phy; - - phy = devm_phy_create(&pdev->dev, child, &miphy28lp_ops); - if (IS_ERR(phy)) { - dev_err(&pdev->dev, "failed to create PHY\n"); - return PTR_ERR(phy); - } - - miphy_dev->phys[port]->phy = phy; - miphy_dev->phys[port]->phydev = miphy_dev; - - ret = miphy28lp_of_probe(child, miphy_phy); - if (ret) - return ret; - - ret = miphy28lp_probe_resets(child, miphy_dev->phys[port]); - if (ret) - return ret; - - phy_set_drvdata(phy, miphy_dev->phys[port]); - port++; - - } - - provider = devm_of_phy_provider_register(&pdev->dev, miphy28lp_xlate); - return PTR_ERR_OR_ZERO(provider); -} - -static const struct of_device_id miphy28lp_of_match[] = { - {.compatible = "st,miphy28lp-phy", }, - {}, -}; - -MODULE_DEVICE_TABLE(of, miphy28lp_of_match); - -static struct platform_driver miphy28lp_driver = { - .probe = miphy28lp_probe, - .driver = { - .name = "miphy28lp-phy", - .owner = THIS_MODULE, - .of_match_table = miphy28lp_of_match, - } -}; - -module_platform_driver(miphy28lp_driver); - -MODULE_AUTHOR("Alexandre Torgue "); -MODULE_DESCRIPTION("STMicroelectronics miphy28lp driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/phy/phy-miphy365x.c b/drivers/phy/phy-miphy365x.c index 98bffbc0f74d..801afaf2d449 100644 --- a/drivers/phy/phy-miphy365x.c +++ b/drivers/phy/phy-miphy365x.c @@ -25,7 +25,7 @@ #include #include -#include +#include #define HFC_TIMEOUT 100 @@ -141,7 +141,7 @@ struct miphy365x_phy { bool pcie_tx_pol_inv; bool sata_tx_pol_inv; u32 sata_gen; - u32 ctrlreg; + u64 ctrlreg; u8 type; }; @@ -176,10 +176,10 @@ static u8 rx_tx_spd[] = { static int miphy365x_set_path(struct miphy365x_phy *miphy_phy, struct miphy365x_dev *miphy_dev) { - bool sata = (miphy_phy->type == PHY_TYPE_SATA); + bool sata = (miphy_phy->type == MIPHY_TYPE_SATA); return regmap_update_bits(miphy_dev->regmap, - miphy_phy->ctrlreg, + (unsigned int)miphy_phy->ctrlreg, SYSCFG_SELECT_SATA_MASK, sata << SYSCFG_SELECT_SATA_POS); } @@ -430,7 +430,7 @@ static int miphy365x_init(struct phy *phy) } /* Initialise Miphy for PCIe or SATA */ - if (miphy_phy->type == PHY_TYPE_PCIE) + if (miphy_phy->type == MIPHY_TYPE_PCIE) ret = miphy365x_init_pcie_port(miphy_phy, miphy_dev); else ret = miphy365x_init_sata_port(miphy_phy, miphy_dev); @@ -445,6 +445,7 @@ int miphy365x_get_addr(struct device *dev, struct miphy365x_phy *miphy_phy, { struct device_node *phynode = miphy_phy->phy->dev.of_node; const char *name; + const __be32 *taddr; int type = miphy_phy->type; int ret; @@ -454,8 +455,24 @@ int miphy365x_get_addr(struct device *dev, struct miphy365x_phy *miphy_phy, return ret; } - if (!((!strncmp(name, "sata", 4) && type == PHY_TYPE_SATA) || - (!strncmp(name, "pcie", 4) && type == PHY_TYPE_PCIE))) + if (!strncmp(name, "syscfg", 6)) { + taddr = of_get_address(phynode, index, NULL, NULL); + if (!taddr) { + dev_err(dev, "failed to fetch syscfg address\n"); + return -EINVAL; + } + + miphy_phy->ctrlreg = of_translate_address(phynode, taddr); + if (miphy_phy->ctrlreg == OF_BAD_ADDR) { + dev_err(dev, "failed to translate syscfg address\n"); + return -EINVAL; + } + + return 0; + } + + if (!((!strncmp(name, "sata", 4) && type == MIPHY_TYPE_SATA) || + (!strncmp(name, "pcie", 4) && type == MIPHY_TYPE_PCIE))) return 0; miphy_phy->base = of_iomap(phynode, index); @@ -498,8 +515,8 @@ static struct phy *miphy365x_xlate(struct device *dev, miphy_phy->type = args->args[0]; - if (!(miphy_phy->type == PHY_TYPE_SATA || - miphy_phy->type == PHY_TYPE_PCIE)) { + if (!(miphy_phy->type == MIPHY_TYPE_SATA || + miphy_phy->type == MIPHY_TYPE_PCIE)) { dev_err(dev, "Unsupported device type: %d\n", miphy_phy->type); return ERR_PTR(-EINVAL); } @@ -576,7 +593,7 @@ static int miphy365x_probe(struct platform_device *pdev) miphy_dev->phys[port] = miphy_phy; - phy = devm_phy_create(&pdev->dev, child, &miphy365x_ops); + phy = devm_phy_create(&pdev->dev, child, &miphy365x_ops, NULL); if (IS_ERR(phy)) { dev_err(&pdev->dev, "failed to create PHY\n"); return PTR_ERR(phy); @@ -589,19 +606,14 @@ static int miphy365x_probe(struct platform_device *pdev) return ret; phy_set_drvdata(phy, miphy_dev->phys[port]); - port++; - /* sysconfig offsets are indexed from 1 */ - ret = of_property_read_u32_index(np, "st,syscfg", port, - &miphy_phy->ctrlreg); - if (ret) { - dev_err(&pdev->dev, "No sysconfig offset found\n"); - return ret; - } } provider = devm_of_phy_provider_register(&pdev->dev, miphy365x_xlate); - return PTR_ERR_OR_ZERO(provider); + if (IS_ERR(provider)) + return PTR_ERR(provider); + + return 0; } static const struct of_device_id miphy365x_of_match[] = { diff --git a/drivers/phy/phy-mvebu-sata.c b/drivers/phy/phy-mvebu-sata.c index 03b94f92e6f1..d395558cb12e 100644 --- a/drivers/phy/phy-mvebu-sata.c +++ b/drivers/phy/phy-mvebu-sata.c @@ -101,7 +101,7 @@ static int phy_mvebu_sata_probe(struct platform_device *pdev) if (IS_ERR(priv->clk)) return PTR_ERR(priv->clk); - phy = devm_phy_create(&pdev->dev, NULL, &phy_mvebu_sata_ops); + phy = devm_phy_create(&pdev->dev, NULL, &phy_mvebu_sata_ops, NULL); if (IS_ERR(phy)) return PTR_ERR(phy); diff --git a/drivers/phy/phy-omap-control.c b/drivers/phy/phy-omap-control.c index a7653d930e6b..c96e8183a8ff 100644 --- a/drivers/phy/phy-omap-control.c +++ b/drivers/phy/phy-omap-control.c @@ -29,9 +29,10 @@ /** * omap_control_pcie_pcs - set the PCS delay count * @dev: the control module device + * @id: index of the pcie PHY (should be 1 or 2) * @delay: 8 bit delay value */ -void omap_control_pcie_pcs(struct device *dev, u8 delay) +void omap_control_pcie_pcs(struct device *dev, u8 id, u8 delay) { u32 val; struct omap_control_phy *control_phy; @@ -54,8 +55,8 @@ void omap_control_pcie_pcs(struct device *dev, u8 delay) val = readl(control_phy->pcie_pcs); val &= ~(OMAP_CTRL_PCIE_PCS_MASK << - OMAP_CTRL_PCIE_PCS_DELAY_COUNT_SHIFT); - val |= (delay << OMAP_CTRL_PCIE_PCS_DELAY_COUNT_SHIFT); + (id * OMAP_CTRL_PCIE_PCS_DELAY_COUNT_SHIFT)); + val |= delay << (id * OMAP_CTRL_PCIE_PCS_DELAY_COUNT_SHIFT); writel(val, control_phy->pcie_pcs); } EXPORT_SYMBOL_GPL(omap_control_pcie_pcs); @@ -216,6 +217,7 @@ void omap_control_usb_set_mode(struct device *dev, return; ctrl_phy = dev_get_drvdata(dev); + if (!ctrl_phy) { dev_err(dev, "Invalid control phy device\n"); return; @@ -240,6 +242,8 @@ void omap_control_usb_set_mode(struct device *dev, } EXPORT_SYMBOL_GPL(omap_control_usb_set_mode); +#ifdef CONFIG_OF + static const enum omap_control_phy_type otghs_data = OMAP_CTRL_TYPE_OTGHS; static const enum omap_control_phy_type usb2_data = OMAP_CTRL_TYPE_USB2; static const enum omap_control_phy_type pipe3_data = OMAP_CTRL_TYPE_PIPE3; @@ -275,6 +279,8 @@ static const struct of_device_id omap_control_phy_id_table[] = { {}, }; MODULE_DEVICE_TABLE(of, omap_control_phy_id_table); +#endif + static int omap_control_phy_probe(struct platform_device *pdev) { @@ -282,7 +288,8 @@ static int omap_control_phy_probe(struct platform_device *pdev) const struct of_device_id *of_id; struct omap_control_phy *control_phy; - of_id = of_match_device(omap_control_phy_id_table, &pdev->dev); + of_id = of_match_device(of_match_ptr(omap_control_phy_id_table), + &pdev->dev); if (!of_id) return -EINVAL; @@ -338,7 +345,7 @@ static struct platform_driver omap_control_phy_driver = { .probe = omap_control_phy_probe, .driver = { .name = "omap-control-phy", - .of_match_table = omap_control_phy_id_table, + .of_match_table = of_match_ptr(omap_control_phy_id_table), }, }; diff --git a/drivers/phy/phy-omap-usb2.c b/drivers/phy/phy-omap-usb2.c index 18b33cedadba..08f2da270837 100644 --- a/drivers/phy/phy-omap-usb2.c +++ b/drivers/phy/phy-omap-usb2.c @@ -144,6 +144,7 @@ static struct phy_ops ops = { .owner = THIS_MODULE, }; +#ifdef CONFIG_OF static const struct usb_phy_data omap_usb2_data = { .label = "omap_usb2", .flags = OMAP_USB2_HAS_START_SRP | OMAP_USB2_HAS_SET_VBUS, @@ -184,6 +185,7 @@ static const struct of_device_id omap_usb2_id_table[] = { {}, }; MODULE_DEVICE_TABLE(of, omap_usb2_id_table); +#endif static int omap_usb2_probe(struct platform_device *pdev) { @@ -198,7 +200,7 @@ static int omap_usb2_probe(struct platform_device *pdev) const struct of_device_id *of_id; struct usb_phy_data *phy_data; - of_id = of_match_device(omap_usb2_id_table, &pdev->dev); + of_id = of_match_device(of_match_ptr(omap_usb2_id_table), &pdev->dev); if (!of_id) return -EINVAL; @@ -254,7 +256,7 @@ static int omap_usb2_probe(struct platform_device *pdev) platform_set_drvdata(pdev, phy); pm_runtime_enable(phy->dev); - generic_phy = devm_phy_create(phy->dev, NULL, &ops); + generic_phy = devm_phy_create(phy->dev, NULL, &ops, NULL); if (IS_ERR(generic_phy)) { pm_runtime_disable(phy->dev); return PTR_ERR(generic_phy); @@ -316,7 +318,7 @@ static int omap_usb2_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_RUNTIME static int omap_usb2_runtime_suspend(struct device *dev) { @@ -375,7 +377,7 @@ static struct platform_driver omap_usb2_driver = { .driver = { .name = "omap-usb2", .pm = DEV_PM_OPS, - .of_match_table = omap_usb2_id_table, + .of_match_table = of_match_ptr(omap_usb2_id_table), }, }; diff --git a/drivers/phy/phy-qcom-apq8064-sata.c b/drivers/phy/phy-qcom-apq8064-sata.c index 4b243f7a10e4..7b3ddfb65898 100644 --- a/drivers/phy/phy-qcom-apq8064-sata.c +++ b/drivers/phy/phy-qcom-apq8064-sata.c @@ -228,7 +228,8 @@ static int qcom_apq8064_sata_phy_probe(struct platform_device *pdev) if (IS_ERR(phy->mmio)) return PTR_ERR(phy->mmio); - generic_phy = devm_phy_create(dev, NULL, &qcom_apq8064_sata_phy_ops); + generic_phy = devm_phy_create(dev, NULL, &qcom_apq8064_sata_phy_ops, + NULL); if (IS_ERR(generic_phy)) { dev_err(dev, "%s: failed to create phy\n", __func__); return PTR_ERR(generic_phy); diff --git a/drivers/phy/phy-qcom-ipq806x-sata.c b/drivers/phy/phy-qcom-ipq806x-sata.c index 6f2fe2627916..759b0bf5b6b3 100644 --- a/drivers/phy/phy-qcom-ipq806x-sata.c +++ b/drivers/phy/phy-qcom-ipq806x-sata.c @@ -150,7 +150,8 @@ static int qcom_ipq806x_sata_phy_probe(struct platform_device *pdev) if (IS_ERR(phy->mmio)) return PTR_ERR(phy->mmio); - generic_phy = devm_phy_create(dev, NULL, &qcom_ipq806x_sata_phy_ops); + generic_phy = devm_phy_create(dev, NULL, &qcom_ipq806x_sata_phy_ops, + NULL); if (IS_ERR(generic_phy)) { dev_err(dev, "%s: failed to create phy\n", __func__); return PTR_ERR(generic_phy); diff --git a/drivers/phy/phy-qcom-ufs-i.h b/drivers/phy/phy-qcom-ufs-i.h deleted file mode 100644 index 591a39175e8a..000000000000 --- a/drivers/phy/phy-qcom-ufs-i.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (c) 2013-2015, Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#ifndef UFS_QCOM_PHY_I_H_ -#define UFS_QCOM_PHY_I_H_ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define readl_poll_timeout(addr, val, cond, sleep_us, timeout_us) \ -({ \ - ktime_t timeout = ktime_add_us(ktime_get(), timeout_us); \ - might_sleep_if(timeout_us); \ - for (;;) { \ - (val) = readl(addr); \ - if (cond) \ - break; \ - if (timeout_us && ktime_compare(ktime_get(), timeout) > 0) { \ - (val) = readl(addr); \ - break; \ - } \ - if (sleep_us) \ - usleep_range(DIV_ROUND_UP(sleep_us, 4), sleep_us); \ - } \ - (cond) ? 0 : -ETIMEDOUT; \ -}) - -#define UFS_QCOM_PHY_CAL_ENTRY(reg, val) \ - { \ - .reg_offset = reg, \ - .cfg_value = val, \ - } - -#define UFS_QCOM_PHY_NAME_LEN 30 - -enum { - MASK_SERDES_START = 0x1, - MASK_PCS_READY = 0x1, -}; - -enum { - OFFSET_SERDES_START = 0x0, -}; - -struct ufs_qcom_phy_stored_attributes { - u32 att; - u32 value; -}; - - -struct ufs_qcom_phy_calibration { - u32 reg_offset; - u32 cfg_value; -}; - -struct ufs_qcom_phy_vreg { - const char *name; - struct regulator *reg; - int max_uA; - int min_uV; - int max_uV; - bool enabled; - bool is_always_on; -}; - -struct ufs_qcom_phy { - struct list_head list; - struct device *dev; - void __iomem *mmio; - void __iomem *dev_ref_clk_ctrl_mmio; - struct clk *tx_iface_clk; - struct clk *rx_iface_clk; - bool is_iface_clk_enabled; - struct clk *ref_clk_src; - struct clk *ref_clk_parent; - struct clk *ref_clk; - bool is_ref_clk_enabled; - bool is_dev_ref_clk_enabled; - struct ufs_qcom_phy_vreg vdda_pll; - struct ufs_qcom_phy_vreg vdda_phy; - struct ufs_qcom_phy_vreg vddp_ref_clk; - unsigned int quirks; - - /* - * If UFS link is put into Hibern8 and if UFS PHY analog hardware is - * power collapsed (by clearing UFS_PHY_POWER_DOWN_CONTROL), Hibern8 - * exit might fail even after powering on UFS PHY analog hardware. - * Enabling this quirk will help to solve above issue by doing - * custom PHY settings just before PHY analog power collapse. - */ - #define UFS_QCOM_PHY_QUIRK_HIBERN8_EXIT_AFTER_PHY_PWR_COLLAPSE BIT(0) - - u8 host_ctrl_rev_major; - u16 host_ctrl_rev_minor; - u16 host_ctrl_rev_step; - - char name[UFS_QCOM_PHY_NAME_LEN]; - struct ufs_qcom_phy_calibration *cached_regs; - int cached_regs_table_size; - bool is_powered_on; - struct ufs_qcom_phy_specific_ops *phy_spec_ops; -}; - -/** - * struct ufs_qcom_phy_specific_ops - set of pointers to functions which have a - * specific implementation per phy. Each UFS phy, should implement - * those functions according to its spec and requirements - * @calibrate_phy: pointer to a function that calibrate the phy - * @start_serdes: pointer to a function that starts the serdes - * @is_physical_coding_sublayer_ready: pointer to a function that - * checks pcs readiness. returns 0 for success and non-zero for error. - * @set_tx_lane_enable: pointer to a function that enable tx lanes - * @power_control: pointer to a function that controls analog rail of phy - * and writes to QSERDES_RX_SIGDET_CNTRL attribute - */ -struct ufs_qcom_phy_specific_ops { - int (*calibrate_phy)(struct ufs_qcom_phy *phy, bool is_rate_B); - void (*start_serdes)(struct ufs_qcom_phy *phy); - int (*is_physical_coding_sublayer_ready)(struct ufs_qcom_phy *phy); - void (*set_tx_lane_enable)(struct ufs_qcom_phy *phy, u32 val); - void (*power_control)(struct ufs_qcom_phy *phy, bool val); -}; - -struct ufs_qcom_phy *get_ufs_qcom_phy(struct phy *generic_phy); -int ufs_qcom_phy_power_on(struct phy *generic_phy); -int ufs_qcom_phy_power_off(struct phy *generic_phy); -int ufs_qcom_phy_exit(struct phy *generic_phy); -int ufs_qcom_phy_init_clks(struct phy *generic_phy, - struct ufs_qcom_phy *phy_common); -int ufs_qcom_phy_init_vregulators(struct phy *generic_phy, - struct ufs_qcom_phy *phy_common); -int ufs_qcom_phy_remove(struct phy *generic_phy, - struct ufs_qcom_phy *ufs_qcom_phy); -struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev, - struct ufs_qcom_phy *common_cfg, - struct phy_ops *ufs_qcom_phy_gen_ops, - struct ufs_qcom_phy_specific_ops *phy_spec_ops); -int ufs_qcom_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy, - struct ufs_qcom_phy_calibration *tbl_A, int tbl_size_A, - struct ufs_qcom_phy_calibration *tbl_B, int tbl_size_B, - bool is_rate_B); -#endif diff --git a/drivers/phy/phy-qcom-ufs-qmp-14nm.c b/drivers/phy/phy-qcom-ufs-qmp-14nm.c deleted file mode 100644 index f5fc50a9fce7..000000000000 --- a/drivers/phy/phy-qcom-ufs-qmp-14nm.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (c) 2013-2015, Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include "phy-qcom-ufs-qmp-14nm.h" - -#define UFS_PHY_NAME "ufs_phy_qmp_14nm" -#define UFS_PHY_VDDA_PHY_UV (925000) - -static -int ufs_qcom_phy_qmp_14nm_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy, - bool is_rate_B) -{ - int tbl_size_A = ARRAY_SIZE(phy_cal_table_rate_A); - int tbl_size_B = ARRAY_SIZE(phy_cal_table_rate_B); - int err; - - err = ufs_qcom_phy_calibrate(ufs_qcom_phy, phy_cal_table_rate_A, - tbl_size_A, phy_cal_table_rate_B, tbl_size_B, is_rate_B); - - if (err) - dev_err(ufs_qcom_phy->dev, - "%s: ufs_qcom_phy_calibrate() failed %d\n", - __func__, err); - return err; -} - -static -void ufs_qcom_phy_qmp_14nm_advertise_quirks(struct ufs_qcom_phy *phy_common) -{ - phy_common->quirks = - UFS_QCOM_PHY_QUIRK_HIBERN8_EXIT_AFTER_PHY_PWR_COLLAPSE; -} - -static int ufs_qcom_phy_qmp_14nm_init(struct phy *generic_phy) -{ - struct ufs_qcom_phy_qmp_14nm *phy = phy_get_drvdata(generic_phy); - struct ufs_qcom_phy *phy_common = &phy->common_cfg; - int err; - - err = ufs_qcom_phy_init_clks(generic_phy, phy_common); - if (err) { - dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_clks() failed %d\n", - __func__, err); - goto out; - } - - err = ufs_qcom_phy_init_vregulators(generic_phy, phy_common); - if (err) { - dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_vregulators() failed %d\n", - __func__, err); - goto out; - } - phy_common->vdda_phy.max_uV = UFS_PHY_VDDA_PHY_UV; - phy_common->vdda_phy.min_uV = UFS_PHY_VDDA_PHY_UV; - - ufs_qcom_phy_qmp_14nm_advertise_quirks(phy_common); - -out: - return err; -} - -static -void ufs_qcom_phy_qmp_14nm_power_control(struct ufs_qcom_phy *phy, bool val) -{ - writel_relaxed(val ? 0x1 : 0x0, phy->mmio + UFS_PHY_POWER_DOWN_CONTROL); - /* - * Before any transactions involving PHY, ensure PHY knows - * that it's analog rail is powered ON (or OFF). - */ - mb(); -} - -static inline -void ufs_qcom_phy_qmp_14nm_set_tx_lane_enable(struct ufs_qcom_phy *phy, u32 val) -{ - /* - * 14nm PHY does not have TX_LANE_ENABLE register. - * Implement this function so as not to propagate error to caller. - */ -} - -static inline void ufs_qcom_phy_qmp_14nm_start_serdes(struct ufs_qcom_phy *phy) -{ - u32 tmp; - - tmp = readl_relaxed(phy->mmio + UFS_PHY_PHY_START); - tmp &= ~MASK_SERDES_START; - tmp |= (1 << OFFSET_SERDES_START); - writel_relaxed(tmp, phy->mmio + UFS_PHY_PHY_START); - /* Ensure register value is committed */ - mb(); -} - -static int ufs_qcom_phy_qmp_14nm_is_pcs_ready(struct ufs_qcom_phy *phy_common) -{ - int err = 0; - u32 val; - - err = readl_poll_timeout(phy_common->mmio + UFS_PHY_PCS_READY_STATUS, - val, (val & MASK_PCS_READY), 10, 1000000); - if (err) - dev_err(phy_common->dev, "%s: poll for pcs failed err = %d\n", - __func__, err); - return err; -} - -static struct phy_ops ufs_qcom_phy_qmp_14nm_phy_ops = { - .init = ufs_qcom_phy_qmp_14nm_init, - .exit = ufs_qcom_phy_exit, - .power_on = ufs_qcom_phy_power_on, - .power_off = ufs_qcom_phy_power_off, - .owner = THIS_MODULE, -}; - -static struct ufs_qcom_phy_specific_ops phy_14nm_ops = { - .calibrate_phy = ufs_qcom_phy_qmp_14nm_phy_calibrate, - .start_serdes = ufs_qcom_phy_qmp_14nm_start_serdes, - .is_physical_coding_sublayer_ready = ufs_qcom_phy_qmp_14nm_is_pcs_ready, - .set_tx_lane_enable = ufs_qcom_phy_qmp_14nm_set_tx_lane_enable, - .power_control = ufs_qcom_phy_qmp_14nm_power_control, -}; - -static int ufs_qcom_phy_qmp_14nm_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct phy *generic_phy; - struct ufs_qcom_phy_qmp_14nm *phy; - int err = 0; - - phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); - if (!phy) { - dev_err(dev, "%s: failed to allocate phy\n", __func__); - err = -ENOMEM; - goto out; - } - - generic_phy = ufs_qcom_phy_generic_probe(pdev, &phy->common_cfg, - &ufs_qcom_phy_qmp_14nm_phy_ops, &phy_14nm_ops); - - if (!generic_phy) { - dev_err(dev, "%s: ufs_qcom_phy_generic_probe() failed\n", - __func__); - err = -EIO; - goto out; - } - - phy_set_drvdata(generic_phy, phy); - - strlcpy(phy->common_cfg.name, UFS_PHY_NAME, - sizeof(phy->common_cfg.name)); - -out: - return err; -} - -static int ufs_qcom_phy_qmp_14nm_remove(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct phy *generic_phy = to_phy(dev); - struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy); - int err = 0; - - err = ufs_qcom_phy_remove(generic_phy, ufs_qcom_phy); - if (err) - dev_err(dev, "%s: ufs_qcom_phy_remove failed = %d\n", - __func__, err); - - return err; -} - -static const struct of_device_id ufs_qcom_phy_qmp_14nm_of_match[] = { - {.compatible = "qcom,ufs-phy-qmp-14nm"}, - {}, -}; -MODULE_DEVICE_TABLE(of, ufs_qcom_phy_qmp_14nm_of_match); - -static struct platform_driver ufs_qcom_phy_qmp_14nm_driver = { - .probe = ufs_qcom_phy_qmp_14nm_probe, - .remove = ufs_qcom_phy_qmp_14nm_remove, - .driver = { - .of_match_table = ufs_qcom_phy_qmp_14nm_of_match, - .name = "ufs_qcom_phy_qmp_14nm", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(ufs_qcom_phy_qmp_14nm_driver); - -MODULE_DESCRIPTION("Universal Flash Storage (UFS) QCOM PHY QMP 14nm"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/phy/phy-qcom-ufs-qmp-14nm.h b/drivers/phy/phy-qcom-ufs-qmp-14nm.h deleted file mode 100644 index 3aefdbacbcd0..000000000000 --- a/drivers/phy/phy-qcom-ufs-qmp-14nm.h +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (c) 2013-2015, Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#ifndef UFS_QCOM_PHY_QMP_14NM_H_ -#define UFS_QCOM_PHY_QMP_14NM_H_ - -#include "phy-qcom-ufs-i.h" - -/* QCOM UFS PHY control registers */ -#define COM_OFF(x) (0x000 + x) -#define PHY_OFF(x) (0xC00 + x) -#define TX_OFF(n, x) (0x400 + (0x400 * n) + x) -#define RX_OFF(n, x) (0x600 + (0x400 * n) + x) - -/* UFS PHY QSERDES COM registers */ -#define QSERDES_COM_BG_TIMER COM_OFF(0x0C) -#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN COM_OFF(0x34) -#define QSERDES_COM_SYS_CLK_CTRL COM_OFF(0x3C) -#define QSERDES_COM_LOCK_CMP1_MODE0 COM_OFF(0x4C) -#define QSERDES_COM_LOCK_CMP2_MODE0 COM_OFF(0x50) -#define QSERDES_COM_LOCK_CMP3_MODE0 COM_OFF(0x54) -#define QSERDES_COM_LOCK_CMP1_MODE1 COM_OFF(0x58) -#define QSERDES_COM_LOCK_CMP2_MODE1 COM_OFF(0x5C) -#define QSERDES_COM_LOCK_CMP3_MODE1 COM_OFF(0x60) -#define QSERDES_COM_CP_CTRL_MODE0 COM_OFF(0x78) -#define QSERDES_COM_CP_CTRL_MODE1 COM_OFF(0x7C) -#define QSERDES_COM_PLL_RCTRL_MODE0 COM_OFF(0x84) -#define QSERDES_COM_PLL_RCTRL_MODE1 COM_OFF(0x88) -#define QSERDES_COM_PLL_CCTRL_MODE0 COM_OFF(0x90) -#define QSERDES_COM_PLL_CCTRL_MODE1 COM_OFF(0x94) -#define QSERDES_COM_SYSCLK_EN_SEL COM_OFF(0xAC) -#define QSERDES_COM_RESETSM_CNTRL COM_OFF(0xB4) -#define QSERDES_COM_LOCK_CMP_EN COM_OFF(0xC8) -#define QSERDES_COM_LOCK_CMP_CFG COM_OFF(0xCC) -#define QSERDES_COM_DEC_START_MODE0 COM_OFF(0xD0) -#define QSERDES_COM_DEC_START_MODE1 COM_OFF(0xD4) -#define QSERDES_COM_DIV_FRAC_START1_MODE0 COM_OFF(0xDC) -#define QSERDES_COM_DIV_FRAC_START2_MODE0 COM_OFF(0xE0) -#define QSERDES_COM_DIV_FRAC_START3_MODE0 COM_OFF(0xE4) -#define QSERDES_COM_DIV_FRAC_START1_MODE1 COM_OFF(0xE8) -#define QSERDES_COM_DIV_FRAC_START2_MODE1 COM_OFF(0xEC) -#define QSERDES_COM_DIV_FRAC_START3_MODE1 COM_OFF(0xF0) -#define QSERDES_COM_INTEGLOOP_GAIN0_MODE0 COM_OFF(0x108) -#define QSERDES_COM_INTEGLOOP_GAIN1_MODE0 COM_OFF(0x10C) -#define QSERDES_COM_INTEGLOOP_GAIN0_MODE1 COM_OFF(0x110) -#define QSERDES_COM_INTEGLOOP_GAIN1_MODE1 COM_OFF(0x114) -#define QSERDES_COM_VCO_TUNE_CTRL COM_OFF(0x124) -#define QSERDES_COM_VCO_TUNE_MAP COM_OFF(0x128) -#define QSERDES_COM_VCO_TUNE1_MODE0 COM_OFF(0x12C) -#define QSERDES_COM_VCO_TUNE2_MODE0 COM_OFF(0x130) -#define QSERDES_COM_VCO_TUNE1_MODE1 COM_OFF(0x134) -#define QSERDES_COM_VCO_TUNE2_MODE1 COM_OFF(0x138) -#define QSERDES_COM_VCO_TUNE_TIMER1 COM_OFF(0x144) -#define QSERDES_COM_VCO_TUNE_TIMER2 COM_OFF(0x148) -#define QSERDES_COM_CLK_SELECT COM_OFF(0x174) -#define QSERDES_COM_HSCLK_SEL COM_OFF(0x178) -#define QSERDES_COM_CORECLK_DIV COM_OFF(0x184) -#define QSERDES_COM_CORE_CLK_EN COM_OFF(0x18C) -#define QSERDES_COM_CMN_CONFIG COM_OFF(0x194) -#define QSERDES_COM_SVS_MODE_CLK_SEL COM_OFF(0x19C) -#define QSERDES_COM_CORECLK_DIV_MODE1 COM_OFF(0x1BC) - -/* UFS PHY registers */ -#define UFS_PHY_PHY_START PHY_OFF(0x00) -#define UFS_PHY_POWER_DOWN_CONTROL PHY_OFF(0x04) -#define UFS_PHY_PCS_READY_STATUS PHY_OFF(0x168) - -/* UFS PHY TX registers */ -#define QSERDES_TX_HIGHZ_TRANSCEIVER_BIAS_DRVR_EN TX_OFF(0, 0x68) -#define QSERDES_TX_LANE_MODE TX_OFF(0, 0x94) - -/* UFS PHY RX registers */ -#define QSERDES_RX_UCDR_FASTLOCK_FO_GAIN RX_OFF(0, 0x40) -#define QSERDES_RX_RX_TERM_BW RX_OFF(0, 0x90) -#define QSERDES_RX_RX_EQ_GAIN1_LSB RX_OFF(0, 0xC4) -#define QSERDES_RX_RX_EQ_GAIN1_MSB RX_OFF(0, 0xC8) -#define QSERDES_RX_RX_EQ_GAIN2_LSB RX_OFF(0, 0xCC) -#define QSERDES_RX_RX_EQ_GAIN2_MSB RX_OFF(0, 0xD0) -#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2 RX_OFF(0, 0xD8) -#define QSERDES_RX_SIGDET_CNTRL RX_OFF(0, 0x114) -#define QSERDES_RX_SIGDET_LVL RX_OFF(0, 0x118) -#define QSERDES_RX_SIGDET_DEGLITCH_CNTRL RX_OFF(0, 0x11C) -#define QSERDES_RX_RX_INTERFACE_MODE RX_OFF(0, 0x12C) - -/* - * This structure represents the 14nm specific phy. - * common_cfg MUST remain the first field in this structure - * in case extra fields are added. This way, when calling - * get_ufs_qcom_phy() of generic phy, we can extract the - * common phy structure (struct ufs_qcom_phy) out of it - * regardless of the relevant specific phy. - */ -struct ufs_qcom_phy_qmp_14nm { - struct ufs_qcom_phy common_cfg; -}; - -static struct ufs_qcom_phy_calibration phy_cal_table_rate_A[] = { - UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_POWER_DOWN_CONTROL, 0x01), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CMN_CONFIG, 0x0e), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_SYSCLK_EN_SEL, 0xd7), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CLK_SELECT, 0x30), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_SYS_CLK_CTRL, 0x06), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_BG_TIMER, 0x0a), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_HSCLK_SEL, 0x05), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CORECLK_DIV, 0x0a), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CORECLK_DIV_MODE1, 0x0a), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP_EN, 0x01), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE_CTRL, 0x10), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_RESETSM_CNTRL, 0x20), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CORE_CLK_EN, 0x00), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP_CFG, 0x00), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE_TIMER1, 0xff), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE_TIMER2, 0x3f), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE_MAP, 0x14), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_SVS_MODE_CLK_SEL, 0x05), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DEC_START_MODE0, 0x82), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x00), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CP_CTRL_MODE0, 0x0b), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE1_MODE0, 0x28), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE2_MODE0, 0x02), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP1_MODE0, 0xff), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP2_MODE0, 0x0c), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DEC_START_MODE1, 0x98), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START1_MODE1, 0x00), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START2_MODE1, 0x00), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START3_MODE1, 0x00), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CP_CTRL_MODE1, 0x0b), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_RCTRL_MODE1, 0x16), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CCTRL_MODE1, 0x28), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_INTEGLOOP_GAIN0_MODE1, 0x80), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_INTEGLOOP_GAIN1_MODE1, 0x00), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE1_MODE1, 0xd6), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE2_MODE1, 0x00), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP1_MODE1, 0x32), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP2_MODE1, 0x0f), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP3_MODE1, 0x00), - - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_HIGHZ_TRANSCEIVER_BIAS_DRVR_EN, 0x45), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_LANE_MODE, 0x02), - - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_SIGDET_LVL, 0x24), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_SIGDET_CNTRL, 0x02), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_INTERFACE_MODE, 0x00), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x18), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0B), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_TERM_BW, 0x5B), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_LSB, 0xFF), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_MSB, 0x3F), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_LSB, 0xFF), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_MSB, 0x0F), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0E), -}; - -static struct ufs_qcom_phy_calibration phy_cal_table_rate_B[] = { - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE_MAP, 0x54), -}; - -#endif diff --git a/drivers/phy/phy-qcom-ufs-qmp-20nm.c b/drivers/phy/phy-qcom-ufs-qmp-20nm.c deleted file mode 100644 index 8332f96b2c4a..000000000000 --- a/drivers/phy/phy-qcom-ufs-qmp-20nm.c +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright (c) 2013-2015, Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include "phy-qcom-ufs-qmp-20nm.h" - -#define UFS_PHY_NAME "ufs_phy_qmp_20nm" - -static -int ufs_qcom_phy_qmp_20nm_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy, - bool is_rate_B) -{ - struct ufs_qcom_phy_calibration *tbl_A, *tbl_B; - int tbl_size_A, tbl_size_B; - u8 major = ufs_qcom_phy->host_ctrl_rev_major; - u16 minor = ufs_qcom_phy->host_ctrl_rev_minor; - u16 step = ufs_qcom_phy->host_ctrl_rev_step; - int err; - - if ((major == 0x1) && (minor == 0x002) && (step == 0x0000)) { - tbl_size_A = ARRAY_SIZE(phy_cal_table_rate_A_1_2_0); - tbl_A = phy_cal_table_rate_A_1_2_0; - } else if ((major == 0x1) && (minor == 0x003) && (step == 0x0000)) { - tbl_size_A = ARRAY_SIZE(phy_cal_table_rate_A_1_3_0); - tbl_A = phy_cal_table_rate_A_1_3_0; - } else { - dev_err(ufs_qcom_phy->dev, "%s: Unknown UFS-PHY version, no calibration values\n", - __func__); - err = -ENODEV; - goto out; - } - - tbl_size_B = ARRAY_SIZE(phy_cal_table_rate_B); - tbl_B = phy_cal_table_rate_B; - - err = ufs_qcom_phy_calibrate(ufs_qcom_phy, tbl_A, tbl_size_A, - tbl_B, tbl_size_B, is_rate_B); - - if (err) - dev_err(ufs_qcom_phy->dev, "%s: ufs_qcom_phy_calibrate() failed %d\n", - __func__, err); - -out: - return err; -} - -static -void ufs_qcom_phy_qmp_20nm_advertise_quirks(struct ufs_qcom_phy *phy_common) -{ - phy_common->quirks = - UFS_QCOM_PHY_QUIRK_HIBERN8_EXIT_AFTER_PHY_PWR_COLLAPSE; -} - -static int ufs_qcom_phy_qmp_20nm_init(struct phy *generic_phy) -{ - struct ufs_qcom_phy_qmp_20nm *phy = phy_get_drvdata(generic_phy); - struct ufs_qcom_phy *phy_common = &phy->common_cfg; - int err = 0; - - err = ufs_qcom_phy_init_clks(generic_phy, phy_common); - if (err) { - dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_clks() failed %d\n", - __func__, err); - goto out; - } - - err = ufs_qcom_phy_init_vregulators(generic_phy, phy_common); - if (err) { - dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_vregulators() failed %d\n", - __func__, err); - goto out; - } - - ufs_qcom_phy_qmp_20nm_advertise_quirks(phy_common); - -out: - return err; -} - -static -void ufs_qcom_phy_qmp_20nm_power_control(struct ufs_qcom_phy *phy, bool val) -{ - bool hibern8_exit_after_pwr_collapse = phy->quirks & - UFS_QCOM_PHY_QUIRK_HIBERN8_EXIT_AFTER_PHY_PWR_COLLAPSE; - - if (val) { - writel_relaxed(0x1, phy->mmio + UFS_PHY_POWER_DOWN_CONTROL); - /* - * Before any transactions involving PHY, ensure PHY knows - * that it's analog rail is powered ON. - */ - mb(); - - if (hibern8_exit_after_pwr_collapse) { - /* - * Give atleast 1us delay after restoring PHY analog - * power. - */ - usleep_range(1, 2); - writel_relaxed(0x0A, phy->mmio + - QSERDES_COM_SYSCLK_EN_SEL_TXBAND); - writel_relaxed(0x08, phy->mmio + - QSERDES_COM_SYSCLK_EN_SEL_TXBAND); - /* - * Make sure workaround is deactivated before proceeding - * with normal PHY operations. - */ - mb(); - } - } else { - if (hibern8_exit_after_pwr_collapse) { - writel_relaxed(0x0A, phy->mmio + - QSERDES_COM_SYSCLK_EN_SEL_TXBAND); - writel_relaxed(0x02, phy->mmio + - QSERDES_COM_SYSCLK_EN_SEL_TXBAND); - /* - * Make sure that above workaround is activated before - * PHY analog power collapse. - */ - mb(); - } - - writel_relaxed(0x0, phy->mmio + UFS_PHY_POWER_DOWN_CONTROL); - /* - * ensure that PHY knows its PHY analog rail is going - * to be powered down - */ - mb(); - } -} - -static -void ufs_qcom_phy_qmp_20nm_set_tx_lane_enable(struct ufs_qcom_phy *phy, u32 val) -{ - writel_relaxed(val & UFS_PHY_TX_LANE_ENABLE_MASK, - phy->mmio + UFS_PHY_TX_LANE_ENABLE); - mb(); -} - -static inline void ufs_qcom_phy_qmp_20nm_start_serdes(struct ufs_qcom_phy *phy) -{ - u32 tmp; - - tmp = readl_relaxed(phy->mmio + UFS_PHY_PHY_START); - tmp &= ~MASK_SERDES_START; - tmp |= (1 << OFFSET_SERDES_START); - writel_relaxed(tmp, phy->mmio + UFS_PHY_PHY_START); - mb(); -} - -static int ufs_qcom_phy_qmp_20nm_is_pcs_ready(struct ufs_qcom_phy *phy_common) -{ - int err = 0; - u32 val; - - err = readl_poll_timeout(phy_common->mmio + UFS_PHY_PCS_READY_STATUS, - val, (val & MASK_PCS_READY), 10, 1000000); - if (err) - dev_err(phy_common->dev, "%s: poll for pcs failed err = %d\n", - __func__, err); - return err; -} - -static struct phy_ops ufs_qcom_phy_qmp_20nm_phy_ops = { - .init = ufs_qcom_phy_qmp_20nm_init, - .exit = ufs_qcom_phy_exit, - .power_on = ufs_qcom_phy_power_on, - .power_off = ufs_qcom_phy_power_off, - .owner = THIS_MODULE, -}; - -static struct ufs_qcom_phy_specific_ops phy_20nm_ops = { - .calibrate_phy = ufs_qcom_phy_qmp_20nm_phy_calibrate, - .start_serdes = ufs_qcom_phy_qmp_20nm_start_serdes, - .is_physical_coding_sublayer_ready = ufs_qcom_phy_qmp_20nm_is_pcs_ready, - .set_tx_lane_enable = ufs_qcom_phy_qmp_20nm_set_tx_lane_enable, - .power_control = ufs_qcom_phy_qmp_20nm_power_control, -}; - -static int ufs_qcom_phy_qmp_20nm_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct phy *generic_phy; - struct ufs_qcom_phy_qmp_20nm *phy; - int err = 0; - - phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); - if (!phy) { - dev_err(dev, "%s: failed to allocate phy\n", __func__); - err = -ENOMEM; - goto out; - } - - generic_phy = ufs_qcom_phy_generic_probe(pdev, &phy->common_cfg, - &ufs_qcom_phy_qmp_20nm_phy_ops, &phy_20nm_ops); - - if (!generic_phy) { - dev_err(dev, "%s: ufs_qcom_phy_generic_probe() failed\n", - __func__); - err = -EIO; - goto out; - } - - phy_set_drvdata(generic_phy, phy); - - strlcpy(phy->common_cfg.name, UFS_PHY_NAME, - sizeof(phy->common_cfg.name)); - -out: - return err; -} - -static int ufs_qcom_phy_qmp_20nm_remove(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct phy *generic_phy = to_phy(dev); - struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy); - int err = 0; - - err = ufs_qcom_phy_remove(generic_phy, ufs_qcom_phy); - if (err) - dev_err(dev, "%s: ufs_qcom_phy_remove failed = %d\n", - __func__, err); - - return err; -} - -static const struct of_device_id ufs_qcom_phy_qmp_20nm_of_match[] = { - {.compatible = "qcom,ufs-phy-qmp-20nm"}, - {}, -}; -MODULE_DEVICE_TABLE(of, ufs_qcom_phy_qmp_20nm_of_match); - -static struct platform_driver ufs_qcom_phy_qmp_20nm_driver = { - .probe = ufs_qcom_phy_qmp_20nm_probe, - .remove = ufs_qcom_phy_qmp_20nm_remove, - .driver = { - .of_match_table = ufs_qcom_phy_qmp_20nm_of_match, - .name = "ufs_qcom_phy_qmp_20nm", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(ufs_qcom_phy_qmp_20nm_driver); - -MODULE_DESCRIPTION("Universal Flash Storage (UFS) QCOM PHY QMP 20nm"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/phy/phy-qcom-ufs-qmp-20nm.h b/drivers/phy/phy-qcom-ufs-qmp-20nm.h deleted file mode 100644 index 4f3076bb3d71..000000000000 --- a/drivers/phy/phy-qcom-ufs-qmp-20nm.h +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright (c) 2013-2015, Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#ifndef UFS_QCOM_PHY_QMP_20NM_H_ -#define UFS_QCOM_PHY_QMP_20NM_H_ - -#include "phy-qcom-ufs-i.h" - -/* QCOM UFS PHY control registers */ - -#define COM_OFF(x) (0x000 + x) -#define PHY_OFF(x) (0xC00 + x) -#define TX_OFF(n, x) (0x400 + (0x400 * n) + x) -#define RX_OFF(n, x) (0x600 + (0x400 * n) + x) - -/* UFS PHY PLL block registers */ -#define QSERDES_COM_SYS_CLK_CTRL COM_OFF(0x0) -#define QSERDES_COM_PLL_VCOTAIL_EN COM_OFF(0x04) -#define QSERDES_COM_PLL_CNTRL COM_OFF(0x14) -#define QSERDES_COM_PLL_IP_SETI COM_OFF(0x24) -#define QSERDES_COM_CORE_CLK_IN_SYNC_SEL COM_OFF(0x28) -#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN COM_OFF(0x30) -#define QSERDES_COM_PLL_CP_SETI COM_OFF(0x34) -#define QSERDES_COM_PLL_IP_SETP COM_OFF(0x38) -#define QSERDES_COM_PLL_CP_SETP COM_OFF(0x3C) -#define QSERDES_COM_SYSCLK_EN_SEL_TXBAND COM_OFF(0x48) -#define QSERDES_COM_RESETSM_CNTRL COM_OFF(0x4C) -#define QSERDES_COM_RESETSM_CNTRL2 COM_OFF(0x50) -#define QSERDES_COM_PLLLOCK_CMP1 COM_OFF(0x90) -#define QSERDES_COM_PLLLOCK_CMP2 COM_OFF(0x94) -#define QSERDES_COM_PLLLOCK_CMP3 COM_OFF(0x98) -#define QSERDES_COM_PLLLOCK_CMP_EN COM_OFF(0x9C) -#define QSERDES_COM_BGTC COM_OFF(0xA0) -#define QSERDES_COM_DEC_START1 COM_OFF(0xAC) -#define QSERDES_COM_PLL_AMP_OS COM_OFF(0xB0) -#define QSERDES_COM_RES_CODE_UP_OFFSET COM_OFF(0xD8) -#define QSERDES_COM_RES_CODE_DN_OFFSET COM_OFF(0xDC) -#define QSERDES_COM_DIV_FRAC_START1 COM_OFF(0x100) -#define QSERDES_COM_DIV_FRAC_START2 COM_OFF(0x104) -#define QSERDES_COM_DIV_FRAC_START3 COM_OFF(0x108) -#define QSERDES_COM_DEC_START2 COM_OFF(0x10C) -#define QSERDES_COM_PLL_RXTXEPCLK_EN COM_OFF(0x110) -#define QSERDES_COM_PLL_CRCTRL COM_OFF(0x114) -#define QSERDES_COM_PLL_CLKEPDIV COM_OFF(0x118) - -/* TX LANE n (0, 1) registers */ -#define QSERDES_TX_EMP_POST1_LVL(n) TX_OFF(n, 0x08) -#define QSERDES_TX_DRV_LVL(n) TX_OFF(n, 0x0C) -#define QSERDES_TX_LANE_MODE(n) TX_OFF(n, 0x54) - -/* RX LANE n (0, 1) registers */ -#define QSERDES_RX_CDR_CONTROL1(n) RX_OFF(n, 0x0) -#define QSERDES_RX_CDR_CONTROL_HALF(n) RX_OFF(n, 0x8) -#define QSERDES_RX_RX_EQ_GAIN1_LSB(n) RX_OFF(n, 0xA8) -#define QSERDES_RX_RX_EQ_GAIN1_MSB(n) RX_OFF(n, 0xAC) -#define QSERDES_RX_RX_EQ_GAIN2_LSB(n) RX_OFF(n, 0xB0) -#define QSERDES_RX_RX_EQ_GAIN2_MSB(n) RX_OFF(n, 0xB4) -#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2(n) RX_OFF(n, 0xBC) -#define QSERDES_RX_CDR_CONTROL_QUARTER(n) RX_OFF(n, 0xC) -#define QSERDES_RX_SIGDET_CNTRL(n) RX_OFF(n, 0x100) - -/* UFS PHY registers */ -#define UFS_PHY_PHY_START PHY_OFF(0x00) -#define UFS_PHY_POWER_DOWN_CONTROL PHY_OFF(0x4) -#define UFS_PHY_TX_LANE_ENABLE PHY_OFF(0x44) -#define UFS_PHY_PWM_G1_CLK_DIVIDER PHY_OFF(0x08) -#define UFS_PHY_PWM_G2_CLK_DIVIDER PHY_OFF(0x0C) -#define UFS_PHY_PWM_G3_CLK_DIVIDER PHY_OFF(0x10) -#define UFS_PHY_PWM_G4_CLK_DIVIDER PHY_OFF(0x14) -#define UFS_PHY_CORECLK_PWM_G1_CLK_DIVIDER PHY_OFF(0x34) -#define UFS_PHY_CORECLK_PWM_G2_CLK_DIVIDER PHY_OFF(0x38) -#define UFS_PHY_CORECLK_PWM_G3_CLK_DIVIDER PHY_OFF(0x3C) -#define UFS_PHY_CORECLK_PWM_G4_CLK_DIVIDER PHY_OFF(0x40) -#define UFS_PHY_OMC_STATUS_RDVAL PHY_OFF(0x68) -#define UFS_PHY_LINE_RESET_TIME PHY_OFF(0x28) -#define UFS_PHY_LINE_RESET_GRANULARITY PHY_OFF(0x2C) -#define UFS_PHY_TSYNC_RSYNC_CNTL PHY_OFF(0x48) -#define UFS_PHY_PLL_CNTL PHY_OFF(0x50) -#define UFS_PHY_TX_LARGE_AMP_DRV_LVL PHY_OFF(0x54) -#define UFS_PHY_TX_SMALL_AMP_DRV_LVL PHY_OFF(0x5C) -#define UFS_PHY_TX_LARGE_AMP_POST_EMP_LVL PHY_OFF(0x58) -#define UFS_PHY_TX_SMALL_AMP_POST_EMP_LVL PHY_OFF(0x60) -#define UFS_PHY_CFG_CHANGE_CNT_VAL PHY_OFF(0x64) -#define UFS_PHY_RX_SYNC_WAIT_TIME PHY_OFF(0x6C) -#define UFS_PHY_TX_MIN_SLEEP_NOCONFIG_TIME_CAPABILITY PHY_OFF(0xB4) -#define UFS_PHY_RX_MIN_SLEEP_NOCONFIG_TIME_CAPABILITY PHY_OFF(0xE0) -#define UFS_PHY_TX_MIN_STALL_NOCONFIG_TIME_CAPABILITY PHY_OFF(0xB8) -#define UFS_PHY_RX_MIN_STALL_NOCONFIG_TIME_CAPABILITY PHY_OFF(0xE4) -#define UFS_PHY_TX_MIN_SAVE_CONFIG_TIME_CAPABILITY PHY_OFF(0xBC) -#define UFS_PHY_RX_MIN_SAVE_CONFIG_TIME_CAPABILITY PHY_OFF(0xE8) -#define UFS_PHY_RX_PWM_BURST_CLOSURE_LENGTH_CAPABILITY PHY_OFF(0xFC) -#define UFS_PHY_RX_MIN_ACTIVATETIME_CAPABILITY PHY_OFF(0x100) -#define UFS_PHY_RX_SIGDET_CTRL3 PHY_OFF(0x14c) -#define UFS_PHY_RMMI_ATTR_CTRL PHY_OFF(0x160) -#define UFS_PHY_RMMI_RX_CFGUPDT_L1 (1 << 7) -#define UFS_PHY_RMMI_TX_CFGUPDT_L1 (1 << 6) -#define UFS_PHY_RMMI_CFGWR_L1 (1 << 5) -#define UFS_PHY_RMMI_CFGRD_L1 (1 << 4) -#define UFS_PHY_RMMI_RX_CFGUPDT_L0 (1 << 3) -#define UFS_PHY_RMMI_TX_CFGUPDT_L0 (1 << 2) -#define UFS_PHY_RMMI_CFGWR_L0 (1 << 1) -#define UFS_PHY_RMMI_CFGRD_L0 (1 << 0) -#define UFS_PHY_RMMI_ATTRID PHY_OFF(0x164) -#define UFS_PHY_RMMI_ATTRWRVAL PHY_OFF(0x168) -#define UFS_PHY_RMMI_ATTRRDVAL_L0_STATUS PHY_OFF(0x16C) -#define UFS_PHY_RMMI_ATTRRDVAL_L1_STATUS PHY_OFF(0x170) -#define UFS_PHY_PCS_READY_STATUS PHY_OFF(0x174) - -#define UFS_PHY_TX_LANE_ENABLE_MASK 0x3 - -/* - * This structure represents the 20nm specific phy. - * common_cfg MUST remain the first field in this structure - * in case extra fields are added. This way, when calling - * get_ufs_qcom_phy() of generic phy, we can extract the - * common phy structure (struct ufs_qcom_phy) out of it - * regardless of the relevant specific phy. - */ -struct ufs_qcom_phy_qmp_20nm { - struct ufs_qcom_phy common_cfg; -}; - -static struct ufs_qcom_phy_calibration phy_cal_table_rate_A_1_2_0[] = { - UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_POWER_DOWN_CONTROL, 0x01), - UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_RX_SIGDET_CTRL3, 0x0D), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_VCOTAIL_EN, 0xe1), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CRCTRL, 0xcc), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_SYSCLK_EN_SEL_TXBAND, 0x08), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CLKEPDIV, 0x03), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_RXTXEPCLK_EN, 0x10), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DEC_START1, 0x82), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DEC_START2, 0x03), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START1, 0x80), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START2, 0x80), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START3, 0x40), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP1, 0xff), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP2, 0x19), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP3, 0x00), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP_EN, 0x03), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_RESETSM_CNTRL, 0x90), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_RESETSM_CNTRL2, 0x03), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL1(0), 0xf2), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL_HALF(0), 0x0c), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL_QUARTER(0), 0x12), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL1(1), 0xf2), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL_HALF(1), 0x0c), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL_QUARTER(1), 0x12), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_LSB(0), 0xff), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_MSB(0), 0xff), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_LSB(0), 0xff), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_MSB(0), 0x00), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_LSB(1), 0xff), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_MSB(1), 0xff), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_LSB(1), 0xff), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_MSB(1), 0x00), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CP_SETI, 0x3f), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_IP_SETP, 0x1b), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CP_SETP, 0x0f), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_IP_SETI, 0x01), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_EMP_POST1_LVL(0), 0x2F), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_DRV_LVL(0), 0x20), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_EMP_POST1_LVL(1), 0x2F), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_DRV_LVL(1), 0x20), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_LANE_MODE(0), 0x68), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_LANE_MODE(1), 0x68), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2(1), 0xdc), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2(0), 0xdc), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x3), -}; - -static struct ufs_qcom_phy_calibration phy_cal_table_rate_A_1_3_0[] = { - UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_POWER_DOWN_CONTROL, 0x01), - UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_RX_SIGDET_CTRL3, 0x0D), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_VCOTAIL_EN, 0xe1), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CRCTRL, 0xcc), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_SYSCLK_EN_SEL_TXBAND, 0x08), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CLKEPDIV, 0x03), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_RXTXEPCLK_EN, 0x10), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DEC_START1, 0x82), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DEC_START2, 0x03), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START1, 0x80), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START2, 0x80), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START3, 0x40), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP1, 0xff), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP2, 0x19), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP3, 0x00), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP_EN, 0x03), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_RESETSM_CNTRL, 0x90), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_RESETSM_CNTRL2, 0x03), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL1(0), 0xf2), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL_HALF(0), 0x0c), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL_QUARTER(0), 0x12), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL1(1), 0xf2), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL_HALF(1), 0x0c), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL_QUARTER(1), 0x12), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_LSB(0), 0xff), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_MSB(0), 0xff), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_LSB(0), 0xff), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_MSB(0), 0x00), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_LSB(1), 0xff), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_MSB(1), 0xff), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_LSB(1), 0xff), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_MSB(1), 0x00), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CP_SETI, 0x2b), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_IP_SETP, 0x38), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CP_SETP, 0x3c), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_RES_CODE_UP_OFFSET, 0x02), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_RES_CODE_DN_OFFSET, 0x02), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_IP_SETI, 0x01), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CNTRL, 0x40), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_LANE_MODE(0), 0x68), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_LANE_MODE(1), 0x68), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2(1), 0xdc), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2(0), 0xdc), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x3), -}; - -static struct ufs_qcom_phy_calibration phy_cal_table_rate_B[] = { - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DEC_START1, 0x98), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP1, 0x65), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP2, 0x1e), -}; - -#endif diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c deleted file mode 100644 index c4199e605ce2..000000000000 --- a/drivers/phy/phy-qcom-ufs.c +++ /dev/null @@ -1,738 +0,0 @@ -/* - * Copyright (c) 2013-2015, Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include "phy-qcom-ufs-i.h" - -#define MAX_PROP_NAME 32 -#define VDDA_PHY_MIN_UV 1000000 -#define VDDA_PHY_MAX_UV 1000000 -#define VDDA_PLL_MIN_UV 1800000 -#define VDDA_PLL_MAX_UV 1800000 -#define VDDP_REF_CLK_MIN_UV 1200000 -#define VDDP_REF_CLK_MAX_UV 1200000 - -static int __ufs_qcom_phy_init_vreg(struct phy *, struct ufs_qcom_phy_vreg *, - const char *, bool); -static int ufs_qcom_phy_init_vreg(struct phy *, struct ufs_qcom_phy_vreg *, - const char *); -static int ufs_qcom_phy_base_init(struct platform_device *pdev, - struct ufs_qcom_phy *phy_common); - -int ufs_qcom_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy, - struct ufs_qcom_phy_calibration *tbl_A, - int tbl_size_A, - struct ufs_qcom_phy_calibration *tbl_B, - int tbl_size_B, bool is_rate_B) -{ - int i; - int ret = 0; - - if (!tbl_A) { - dev_err(ufs_qcom_phy->dev, "%s: tbl_A is NULL", __func__); - ret = EINVAL; - goto out; - } - - for (i = 0; i < tbl_size_A; i++) - writel_relaxed(tbl_A[i].cfg_value, - ufs_qcom_phy->mmio + tbl_A[i].reg_offset); - - /* - * In case we would like to work in rate B, we need - * to override a registers that were configured in rate A table - * with registers of rate B table. - * table. - */ - if (is_rate_B) { - if (!tbl_B) { - dev_err(ufs_qcom_phy->dev, "%s: tbl_B is NULL", - __func__); - ret = EINVAL; - goto out; - } - - for (i = 0; i < tbl_size_B; i++) - writel_relaxed(tbl_B[i].cfg_value, - ufs_qcom_phy->mmio + tbl_B[i].reg_offset); - } - - /* flush buffered writes */ - mb(); - -out: - return ret; -} -EXPORT_SYMBOL_GPL(ufs_qcom_phy_calibrate); - -struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev, - struct ufs_qcom_phy *common_cfg, - struct phy_ops *ufs_qcom_phy_gen_ops, - struct ufs_qcom_phy_specific_ops *phy_spec_ops) -{ - int err; - struct device *dev = &pdev->dev; - struct phy *generic_phy = NULL; - struct phy_provider *phy_provider; - - err = ufs_qcom_phy_base_init(pdev, common_cfg); - if (err) { - dev_err(dev, "%s: phy base init failed %d\n", __func__, err); - goto out; - } - - phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); - if (IS_ERR(phy_provider)) { - err = PTR_ERR(phy_provider); - dev_err(dev, "%s: failed to register phy %d\n", __func__, err); - goto out; - } - - generic_phy = devm_phy_create(dev, NULL, ufs_qcom_phy_gen_ops); - if (IS_ERR(generic_phy)) { - err = PTR_ERR(generic_phy); - dev_err(dev, "%s: failed to create phy %d\n", __func__, err); - generic_phy = NULL; - goto out; - } - - common_cfg->phy_spec_ops = phy_spec_ops; - common_cfg->dev = dev; - -out: - return generic_phy; -} -EXPORT_SYMBOL_GPL(ufs_qcom_phy_generic_probe); - -/* - * This assumes the embedded phy structure inside generic_phy is of type - * struct ufs_qcom_phy. In order to function properly it's crucial - * to keep the embedded struct "struct ufs_qcom_phy common_cfg" - * as the first inside generic_phy. - */ -struct ufs_qcom_phy *get_ufs_qcom_phy(struct phy *generic_phy) -{ - return (struct ufs_qcom_phy *)phy_get_drvdata(generic_phy); -} -EXPORT_SYMBOL_GPL(get_ufs_qcom_phy); - -static -int ufs_qcom_phy_base_init(struct platform_device *pdev, - struct ufs_qcom_phy *phy_common) -{ - struct device *dev = &pdev->dev; - struct resource *res; - int err = 0; - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_mem"); - phy_common->mmio = devm_ioremap_resource(dev, res); - if (IS_ERR((void const *)phy_common->mmio)) { - err = PTR_ERR((void const *)phy_common->mmio); - phy_common->mmio = NULL; - dev_err(dev, "%s: ioremap for phy_mem resource failed %d\n", - __func__, err); - return err; - } - - /* "dev_ref_clk_ctrl_mem" is optional resource */ - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, - "dev_ref_clk_ctrl_mem"); - phy_common->dev_ref_clk_ctrl_mmio = devm_ioremap_resource(dev, res); - if (IS_ERR((void const *)phy_common->dev_ref_clk_ctrl_mmio)) - phy_common->dev_ref_clk_ctrl_mmio = NULL; - - return 0; -} - -static int __ufs_qcom_phy_clk_get(struct phy *phy, - const char *name, struct clk **clk_out, bool err_print) -{ - struct clk *clk; - int err = 0; - struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(phy); - struct device *dev = ufs_qcom_phy->dev; - - clk = devm_clk_get(dev, name); - if (IS_ERR(clk)) { - err = PTR_ERR(clk); - if (err_print) - dev_err(dev, "failed to get %s err %d", name, err); - } else { - *clk_out = clk; - } - - return err; -} - -static -int ufs_qcom_phy_clk_get(struct phy *phy, - const char *name, struct clk **clk_out) -{ - return __ufs_qcom_phy_clk_get(phy, name, clk_out, true); -} - -int -ufs_qcom_phy_init_clks(struct phy *generic_phy, - struct ufs_qcom_phy *phy_common) -{ - int err; - - err = ufs_qcom_phy_clk_get(generic_phy, "tx_iface_clk", - &phy_common->tx_iface_clk); - if (err) - goto out; - - err = ufs_qcom_phy_clk_get(generic_phy, "rx_iface_clk", - &phy_common->rx_iface_clk); - if (err) - goto out; - - err = ufs_qcom_phy_clk_get(generic_phy, "ref_clk_src", - &phy_common->ref_clk_src); - if (err) - goto out; - - /* - * "ref_clk_parent" is optional hence don't abort init if it's not - * found. - */ - __ufs_qcom_phy_clk_get(generic_phy, "ref_clk_parent", - &phy_common->ref_clk_parent, false); - - err = ufs_qcom_phy_clk_get(generic_phy, "ref_clk", - &phy_common->ref_clk); - -out: - return err; -} -EXPORT_SYMBOL_GPL(ufs_qcom_phy_init_clks); - -int -ufs_qcom_phy_init_vregulators(struct phy *generic_phy, - struct ufs_qcom_phy *phy_common) -{ - int err; - - err = ufs_qcom_phy_init_vreg(generic_phy, &phy_common->vdda_pll, - "vdda-pll"); - if (err) - goto out; - - err = ufs_qcom_phy_init_vreg(generic_phy, &phy_common->vdda_phy, - "vdda-phy"); - - if (err) - goto out; - - /* vddp-ref-clk-* properties are optional */ - __ufs_qcom_phy_init_vreg(generic_phy, &phy_common->vddp_ref_clk, - "vddp-ref-clk", true); -out: - return err; -} -EXPORT_SYMBOL_GPL(ufs_qcom_phy_init_vregulators); - -static int __ufs_qcom_phy_init_vreg(struct phy *phy, - struct ufs_qcom_phy_vreg *vreg, const char *name, bool optional) -{ - int err = 0; - struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(phy); - struct device *dev = ufs_qcom_phy->dev; - - char prop_name[MAX_PROP_NAME]; - - vreg->name = kstrdup(name, GFP_KERNEL); - if (!vreg->name) { - err = -ENOMEM; - goto out; - } - - vreg->reg = devm_regulator_get(dev, name); - if (IS_ERR(vreg->reg)) { - err = PTR_ERR(vreg->reg); - vreg->reg = NULL; - if (!optional) - dev_err(dev, "failed to get %s, %d\n", name, err); - goto out; - } - - if (dev->of_node) { - snprintf(prop_name, MAX_PROP_NAME, "%s-max-microamp", name); - err = of_property_read_u32(dev->of_node, - prop_name, &vreg->max_uA); - if (err && err != -EINVAL) { - dev_err(dev, "%s: failed to read %s\n", - __func__, prop_name); - goto out; - } else if (err == -EINVAL || !vreg->max_uA) { - if (regulator_count_voltages(vreg->reg) > 0) { - dev_err(dev, "%s: %s is mandatory\n", - __func__, prop_name); - goto out; - } - err = 0; - } - snprintf(prop_name, MAX_PROP_NAME, "%s-always-on", name); - if (of_get_property(dev->of_node, prop_name, NULL)) - vreg->is_always_on = true; - else - vreg->is_always_on = false; - } - - if (!strcmp(name, "vdda-pll")) { - vreg->max_uV = VDDA_PLL_MAX_UV; - vreg->min_uV = VDDA_PLL_MIN_UV; - } else if (!strcmp(name, "vdda-phy")) { - vreg->max_uV = VDDA_PHY_MAX_UV; - vreg->min_uV = VDDA_PHY_MIN_UV; - } else if (!strcmp(name, "vddp-ref-clk")) { - vreg->max_uV = VDDP_REF_CLK_MAX_UV; - vreg->min_uV = VDDP_REF_CLK_MIN_UV; - } - -out: - if (err) - kfree(vreg->name); - return err; -} - -static int ufs_qcom_phy_init_vreg(struct phy *phy, - struct ufs_qcom_phy_vreg *vreg, const char *name) -{ - return __ufs_qcom_phy_init_vreg(phy, vreg, name, false); -} - -static -int ufs_qcom_phy_cfg_vreg(struct phy *phy, - struct ufs_qcom_phy_vreg *vreg, bool on) -{ - int ret = 0; - struct regulator *reg = vreg->reg; - const char *name = vreg->name; - int min_uV; - int uA_load; - struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(phy); - struct device *dev = ufs_qcom_phy->dev; - - BUG_ON(!vreg); - - if (regulator_count_voltages(reg) > 0) { - min_uV = on ? vreg->min_uV : 0; - ret = regulator_set_voltage(reg, min_uV, vreg->max_uV); - if (ret) { - dev_err(dev, "%s: %s set voltage failed, err=%d\n", - __func__, name, ret); - goto out; - } - uA_load = on ? vreg->max_uA : 0; - ret = regulator_set_optimum_mode(reg, uA_load); - if (ret >= 0) { - /* - * regulator_set_optimum_mode() returns new regulator - * mode upon success. - */ - ret = 0; - } else { - dev_err(dev, "%s: %s set optimum mode(uA_load=%d) failed, err=%d\n", - __func__, name, uA_load, ret); - goto out; - } - } -out: - return ret; -} - -static -int ufs_qcom_phy_enable_vreg(struct phy *phy, - struct ufs_qcom_phy_vreg *vreg) -{ - struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(phy); - struct device *dev = ufs_qcom_phy->dev; - int ret = 0; - - if (!vreg || vreg->enabled) - goto out; - - ret = ufs_qcom_phy_cfg_vreg(phy, vreg, true); - if (ret) { - dev_err(dev, "%s: ufs_qcom_phy_cfg_vreg() failed, err=%d\n", - __func__, ret); - goto out; - } - - ret = regulator_enable(vreg->reg); - if (ret) { - dev_err(dev, "%s: enable failed, err=%d\n", - __func__, ret); - goto out; - } - - vreg->enabled = true; -out: - return ret; -} - -int ufs_qcom_phy_enable_ref_clk(struct phy *generic_phy) -{ - int ret = 0; - struct ufs_qcom_phy *phy = get_ufs_qcom_phy(generic_phy); - - if (phy->is_ref_clk_enabled) - goto out; - - /* - * reference clock is propagated in a daisy-chained manner from - * source to phy, so ungate them at each stage. - */ - ret = clk_prepare_enable(phy->ref_clk_src); - if (ret) { - dev_err(phy->dev, "%s: ref_clk_src enable failed %d\n", - __func__, ret); - goto out; - } - - /* - * "ref_clk_parent" is optional clock hence make sure that clk reference - * is available before trying to enable the clock. - */ - if (phy->ref_clk_parent) { - ret = clk_prepare_enable(phy->ref_clk_parent); - if (ret) { - dev_err(phy->dev, "%s: ref_clk_parent enable failed %d\n", - __func__, ret); - goto out_disable_src; - } - } - - ret = clk_prepare_enable(phy->ref_clk); - if (ret) { - dev_err(phy->dev, "%s: ref_clk enable failed %d\n", - __func__, ret); - goto out_disable_parent; - } - - phy->is_ref_clk_enabled = true; - goto out; - -out_disable_parent: - if (phy->ref_clk_parent) - clk_disable_unprepare(phy->ref_clk_parent); -out_disable_src: - clk_disable_unprepare(phy->ref_clk_src); -out: - return ret; -} - -static -int ufs_qcom_phy_disable_vreg(struct phy *phy, - struct ufs_qcom_phy_vreg *vreg) -{ - struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(phy); - struct device *dev = ufs_qcom_phy->dev; - int ret = 0; - - if (!vreg || !vreg->enabled || vreg->is_always_on) - goto out; - - ret = regulator_disable(vreg->reg); - - if (!ret) { - /* ignore errors on applying disable config */ - ufs_qcom_phy_cfg_vreg(phy, vreg, false); - vreg->enabled = false; - } else { - dev_err(dev, "%s: %s disable failed, err=%d\n", - __func__, vreg->name, ret); - } -out: - return ret; -} - -void ufs_qcom_phy_disable_ref_clk(struct phy *generic_phy) -{ - struct ufs_qcom_phy *phy = get_ufs_qcom_phy(generic_phy); - - if (phy->is_ref_clk_enabled) { - clk_disable_unprepare(phy->ref_clk); - /* - * "ref_clk_parent" is optional clock hence make sure that clk - * reference is available before trying to disable the clock. - */ - if (phy->ref_clk_parent) - clk_disable_unprepare(phy->ref_clk_parent); - clk_disable_unprepare(phy->ref_clk_src); - phy->is_ref_clk_enabled = false; - } -} - -#define UFS_REF_CLK_EN (1 << 5) - -static void ufs_qcom_phy_dev_ref_clk_ctrl(struct phy *generic_phy, bool enable) -{ - struct ufs_qcom_phy *phy = get_ufs_qcom_phy(generic_phy); - - if (phy->dev_ref_clk_ctrl_mmio && - (enable ^ phy->is_dev_ref_clk_enabled)) { - u32 temp = readl_relaxed(phy->dev_ref_clk_ctrl_mmio); - - if (enable) - temp |= UFS_REF_CLK_EN; - else - temp &= ~UFS_REF_CLK_EN; - - /* - * If we are here to disable this clock immediately after - * entering into hibern8, we need to make sure that device - * ref_clk is active atleast 1us after the hibern8 enter. - */ - if (!enable) - udelay(1); - - writel_relaxed(temp, phy->dev_ref_clk_ctrl_mmio); - /* ensure that ref_clk is enabled/disabled before we return */ - wmb(); - /* - * If we call hibern8 exit after this, we need to make sure that - * device ref_clk is stable for atleast 1us before the hibern8 - * exit command. - */ - if (enable) - udelay(1); - - phy->is_dev_ref_clk_enabled = enable; - } -} - -void ufs_qcom_phy_enable_dev_ref_clk(struct phy *generic_phy) -{ - ufs_qcom_phy_dev_ref_clk_ctrl(generic_phy, true); -} - -void ufs_qcom_phy_disable_dev_ref_clk(struct phy *generic_phy) -{ - ufs_qcom_phy_dev_ref_clk_ctrl(generic_phy, false); -} - -/* Turn ON M-PHY RMMI interface clocks */ -int ufs_qcom_phy_enable_iface_clk(struct phy *generic_phy) -{ - struct ufs_qcom_phy *phy = get_ufs_qcom_phy(generic_phy); - int ret = 0; - - if (phy->is_iface_clk_enabled) - goto out; - - ret = clk_prepare_enable(phy->tx_iface_clk); - if (ret) { - dev_err(phy->dev, "%s: tx_iface_clk enable failed %d\n", - __func__, ret); - goto out; - } - ret = clk_prepare_enable(phy->rx_iface_clk); - if (ret) { - clk_disable_unprepare(phy->tx_iface_clk); - dev_err(phy->dev, "%s: rx_iface_clk enable failed %d. disabling also tx_iface_clk\n", - __func__, ret); - goto out; - } - phy->is_iface_clk_enabled = true; - -out: - return ret; -} - -/* Turn OFF M-PHY RMMI interface clocks */ -void ufs_qcom_phy_disable_iface_clk(struct phy *generic_phy) -{ - struct ufs_qcom_phy *phy = get_ufs_qcom_phy(generic_phy); - - if (phy->is_iface_clk_enabled) { - clk_disable_unprepare(phy->tx_iface_clk); - clk_disable_unprepare(phy->rx_iface_clk); - phy->is_iface_clk_enabled = false; - } -} - -int ufs_qcom_phy_start_serdes(struct phy *generic_phy) -{ - struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy); - int ret = 0; - - if (!ufs_qcom_phy->phy_spec_ops->start_serdes) { - dev_err(ufs_qcom_phy->dev, "%s: start_serdes() callback is not supported\n", - __func__); - ret = -ENOTSUPP; - } else { - ufs_qcom_phy->phy_spec_ops->start_serdes(ufs_qcom_phy); - } - - return ret; -} - -int ufs_qcom_phy_set_tx_lane_enable(struct phy *generic_phy, u32 tx_lanes) -{ - struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy); - int ret = 0; - - if (!ufs_qcom_phy->phy_spec_ops->set_tx_lane_enable) { - dev_err(ufs_qcom_phy->dev, "%s: set_tx_lane_enable() callback is not supported\n", - __func__); - ret = -ENOTSUPP; - } else { - ufs_qcom_phy->phy_spec_ops->set_tx_lane_enable(ufs_qcom_phy, - tx_lanes); - } - - return ret; -} - -void ufs_qcom_phy_save_controller_version(struct phy *generic_phy, - u8 major, u16 minor, u16 step) -{ - struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy); - - ufs_qcom_phy->host_ctrl_rev_major = major; - ufs_qcom_phy->host_ctrl_rev_minor = minor; - ufs_qcom_phy->host_ctrl_rev_step = step; -} - -int ufs_qcom_phy_calibrate_phy(struct phy *generic_phy, bool is_rate_B) -{ - struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy); - int ret = 0; - - if (!ufs_qcom_phy->phy_spec_ops->calibrate_phy) { - dev_err(ufs_qcom_phy->dev, "%s: calibrate_phy() callback is not supported\n", - __func__); - ret = -ENOTSUPP; - } else { - ret = ufs_qcom_phy->phy_spec_ops-> - calibrate_phy(ufs_qcom_phy, is_rate_B); - if (ret) - dev_err(ufs_qcom_phy->dev, "%s: calibrate_phy() failed %d\n", - __func__, ret); - } - - return ret; -} - -int ufs_qcom_phy_remove(struct phy *generic_phy, - struct ufs_qcom_phy *ufs_qcom_phy) -{ - phy_power_off(generic_phy); - - kfree(ufs_qcom_phy->vdda_pll.name); - kfree(ufs_qcom_phy->vdda_phy.name); - - return 0; -} -EXPORT_SYMBOL_GPL(ufs_qcom_phy_remove); - -int ufs_qcom_phy_exit(struct phy *generic_phy) -{ - struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy); - - if (ufs_qcom_phy->is_powered_on) - phy_power_off(generic_phy); - - return 0; -} -EXPORT_SYMBOL_GPL(ufs_qcom_phy_exit); - -int ufs_qcom_phy_is_pcs_ready(struct phy *generic_phy) -{ - struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy); - - if (!ufs_qcom_phy->phy_spec_ops->is_physical_coding_sublayer_ready) { - dev_err(ufs_qcom_phy->dev, "%s: is_physical_coding_sublayer_ready() callback is not supported\n", - __func__); - return -ENOTSUPP; - } - - return ufs_qcom_phy->phy_spec_ops-> - is_physical_coding_sublayer_ready(ufs_qcom_phy); -} - -int ufs_qcom_phy_power_on(struct phy *generic_phy) -{ - struct ufs_qcom_phy *phy_common = get_ufs_qcom_phy(generic_phy); - struct device *dev = phy_common->dev; - int err; - - err = ufs_qcom_phy_enable_vreg(generic_phy, &phy_common->vdda_phy); - if (err) { - dev_err(dev, "%s enable vdda_phy failed, err=%d\n", - __func__, err); - goto out; - } - - phy_common->phy_spec_ops->power_control(phy_common, true); - - /* vdda_pll also enables ref clock LDOs so enable it first */ - err = ufs_qcom_phy_enable_vreg(generic_phy, &phy_common->vdda_pll); - if (err) { - dev_err(dev, "%s enable vdda_pll failed, err=%d\n", - __func__, err); - goto out_disable_phy; - } - - err = ufs_qcom_phy_enable_ref_clk(generic_phy); - if (err) { - dev_err(dev, "%s enable phy ref clock failed, err=%d\n", - __func__, err); - goto out_disable_pll; - } - - /* enable device PHY ref_clk pad rail */ - if (phy_common->vddp_ref_clk.reg) { - err = ufs_qcom_phy_enable_vreg(generic_phy, - &phy_common->vddp_ref_clk); - if (err) { - dev_err(dev, "%s enable vddp_ref_clk failed, err=%d\n", - __func__, err); - goto out_disable_ref_clk; - } - } - - phy_common->is_powered_on = true; - goto out; - -out_disable_ref_clk: - ufs_qcom_phy_disable_ref_clk(generic_phy); -out_disable_pll: - ufs_qcom_phy_disable_vreg(generic_phy, &phy_common->vdda_pll); -out_disable_phy: - ufs_qcom_phy_disable_vreg(generic_phy, &phy_common->vdda_phy); -out: - return err; -} -EXPORT_SYMBOL_GPL(ufs_qcom_phy_power_on); - -int ufs_qcom_phy_power_off(struct phy *generic_phy) -{ - struct ufs_qcom_phy *phy_common = get_ufs_qcom_phy(generic_phy); - - phy_common->phy_spec_ops->power_control(phy_common, false); - - if (phy_common->vddp_ref_clk.reg) - ufs_qcom_phy_disable_vreg(generic_phy, - &phy_common->vddp_ref_clk); - ufs_qcom_phy_disable_ref_clk(generic_phy); - - ufs_qcom_phy_disable_vreg(generic_phy, &phy_common->vdda_pll); - ufs_qcom_phy_disable_vreg(generic_phy, &phy_common->vdda_phy); - phy_common->is_powered_on = false; - - return 0; -} -EXPORT_SYMBOL_GPL(ufs_qcom_phy_power_off); diff --git a/drivers/phy/phy-rcar-gen2.c b/drivers/phy/phy-rcar-gen2.c index 778276aba3aa..2793af17799f 100644 --- a/drivers/phy/phy-rcar-gen2.c +++ b/drivers/phy/phy-rcar-gen2.c @@ -304,7 +304,7 @@ static int rcar_gen2_phy_probe(struct platform_device *pdev) phy->select_value = select_value[channel_num][n]; phy->phy = devm_phy_create(dev, NULL, - &rcar_gen2_phy_ops); + &rcar_gen2_phy_ops, NULL); if (IS_ERR(phy->phy)) { dev_err(dev, "Failed to create PHY\n"); return PTR_ERR(phy->phy); diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c index c1d94dcc0bab..2586b767bcb2 100644 --- a/drivers/phy/phy-rockchip-usb.c +++ b/drivers/phy/phy-rockchip-usb.c @@ -1,7 +1,7 @@ /* * Rockchip usb PHY driver * - * Copyright (C) 2014 Yunzhi Li + * Copyright (C) 2014 Roy Li * Copyright (C) 2014 ROCKCHIP, Inc. * * This program is free software; you can redistribute it and/or modify @@ -28,26 +28,31 @@ #include #include -/* - * The higher 16-bit of this register is used for write protection - * only if BIT(13 + 16) set to 1 the BIT(13) can be written. - */ -#define SIDDQ_WRITE_ENA BIT(29) -#define SIDDQ_ON BIT(13) +#define ROCKCHIP_RK3288_UOC(n) (0x320 + n * 0x14) + +#define SIDDQ_MSK (1 << (13 + 16)) +#define SIDDQ_ON (1 << 13) #define SIDDQ_OFF (0 << 13) +enum rk3288_phy_id { + RK3288_OTG, + RK3288_HOST0, + RK3288_HOST1, + RK3288_NUM_PHYS, +}; + struct rockchip_usb_phy { - unsigned int reg_offset; - struct regmap *reg_base; - struct clk *clk; - struct phy *phy; + struct regmap *reg_base; + unsigned int reg_offset; + struct clk *clk; + struct phy *phy; }; static int rockchip_usb_phy_power(struct rockchip_usb_phy *phy, bool siddq) { return regmap_write(phy->reg_base, phy->reg_offset, - SIDDQ_WRITE_ENA | (siddq ? SIDDQ_ON : SIDDQ_OFF)); + SIDDQ_MSK | (siddq ? SIDDQ_ON : SIDDQ_OFF)); } static int rockchip_usb_phy_power_off(struct phy *_phy) @@ -55,7 +60,7 @@ static int rockchip_usb_phy_power_off(struct phy *_phy) struct rockchip_usb_phy *phy = phy_get_drvdata(_phy); int ret = 0; - /* Power down usb phy analog blocks by set siddq 1 */ + /* Power down usb phy analog blocks by set siddq 1*/ ret = rockchip_usb_phy_power(phy, 1); if (ret) return ret; @@ -76,7 +81,7 @@ static int rockchip_usb_phy_power_on(struct phy *_phy) if (ret) return ret; - /* Power up usb phy analog blocks by set siddq 0 */ + /* Power up usb phy analog blocks by set siddq 0*/ ret = rockchip_usb_phy_power(phy, 0); if (ret) return ret; @@ -84,6 +89,17 @@ static int rockchip_usb_phy_power_on(struct phy *_phy) return 0; } +static struct phy *rockchip_usb_phy_xlate(struct device *dev, + struct of_phandle_args *args) +{ + struct rockchip_usb_phy *phy_array = dev_get_drvdata(dev); + + if (WARN_ON(args->args[0] == 0 || args->args[0] >= RK3288_NUM_PHYS)) + return ERR_PTR(-ENODEV); + + return (phy_array + args->args[0])->phy; +} + static struct phy_ops ops = { .power_on = rockchip_usb_phy_power_on, .power_off = rockchip_usb_phy_power_off, @@ -94,10 +110,11 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct rockchip_usb_phy *rk_phy; + struct rockchip_usb_phy *phy_array; struct phy_provider *phy_provider; - struct device_node *child; struct regmap *grf; - unsigned int reg_offset; + char clk_name[16]; + int i; grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf"); if (IS_ERR(grf)) { @@ -105,37 +122,38 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev) return PTR_ERR(grf); } - for_each_available_child_of_node(dev->of_node, child) { - rk_phy = devm_kzalloc(dev, sizeof(*rk_phy), GFP_KERNEL); - if (!rk_phy) - return -ENOMEM; + phy_array = devm_kzalloc(dev, RK3288_NUM_PHYS * sizeof(*rk_phy), + GFP_KERNEL); + if (!phy_array) + return -ENOMEM; - if (of_property_read_u32(child, "reg", ®_offset)) { - dev_err(dev, "missing reg property in node %s\n", - child->name); - return -EINVAL; - } + for (i = 0; i < RK3288_NUM_PHYS; i++) { + rk_phy = &phy_array[i]; - rk_phy->reg_offset = reg_offset; rk_phy->reg_base = grf; - rk_phy->clk = of_clk_get_by_name(child, "phyclk"); - if (IS_ERR(rk_phy->clk)) + rk_phy->reg_offset = ROCKCHIP_RK3288_UOC(i); + + snprintf(clk_name, sizeof(clk_name), "usbphy%d", i); + rk_phy->clk = devm_clk_get(dev, clk_name); + if (IS_ERR(rk_phy->clk)) { + dev_warn(dev, "failed to get clock %s\n", clk_name); rk_phy->clk = NULL; + } - rk_phy->phy = devm_phy_create(dev, child, &ops); + rk_phy->phy = devm_phy_create(dev, NULL, &ops, NULL); if (IS_ERR(rk_phy->phy)) { - dev_err(dev, "failed to create PHY\n"); + dev_err(dev, "failed to create PHY %d\n", i); return PTR_ERR(rk_phy->phy); } phy_set_drvdata(rk_phy->phy, rk_phy); } - phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); - if (PTR_ERR(phy_provider)) - return (long)phy_provider; - else - return 0; + platform_set_drvdata(pdev, phy_array); + + phy_provider = devm_of_phy_provider_register(dev, + rockchip_usb_phy_xlate); + return PTR_ERR_OR_ZERO(phy_provider); } static const struct of_device_id rockchip_usb_phy_dt_ids[] = { @@ -156,6 +174,6 @@ static struct platform_driver rockchip_usb_driver = { module_platform_driver(rockchip_usb_driver); -MODULE_AUTHOR("Yunzhi Li "); +MODULE_AUTHOR("Roy Li "); MODULE_DESCRIPTION("Rockchip USB 2.0 PHY driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/phy/phy-samsung-usb2.c b/drivers/phy/phy-samsung-usb2.c index 55b6994932e3..908949dfb4db 100644 --- a/drivers/phy/phy-samsung-usb2.c +++ b/drivers/phy/phy-samsung-usb2.c @@ -37,14 +37,10 @@ static int samsung_usb2_phy_power_on(struct phy *phy) spin_lock(&drv->lock); ret = inst->cfg->power_on(inst); spin_unlock(&drv->lock); - if (ret) - goto err_power_on; } return 0; -err_power_on: - clk_disable_unprepare(drv->ref_clk); err_instance_clk: clk_disable_unprepare(drv->clk); err_main_clk: @@ -55,7 +51,7 @@ static int samsung_usb2_phy_power_off(struct phy *phy) { struct samsung_usb2_phy_instance *inst = phy_get_drvdata(phy); struct samsung_usb2_phy_driver *drv = inst->drv; - int ret; + int ret = 0; dev_dbg(drv->dev, "Request to power_off \"%s\" usb phy\n", inst->cfg->label); @@ -63,12 +59,10 @@ static int samsung_usb2_phy_power_off(struct phy *phy) spin_lock(&drv->lock); ret = inst->cfg->power_off(inst); spin_unlock(&drv->lock); - if (ret) - return ret; } clk_disable_unprepare(drv->ref_clk); clk_disable_unprepare(drv->clk); - return 0; + return ret; } static struct phy_ops samsung_usb2_phy_ops = { @@ -208,7 +202,8 @@ static int samsung_usb2_phy_probe(struct platform_device *pdev) struct samsung_usb2_phy_instance *p = &drv->instances[i]; dev_dbg(dev, "Creating phy \"%s\"\n", label); - p->phy = devm_phy_create(dev, NULL, &samsung_usb2_phy_ops); + p->phy = devm_phy_create(dev, NULL, &samsung_usb2_phy_ops, + NULL); if (IS_ERR(p->phy)) { dev_err(drv->dev, "Failed to create usb2_phy \"%s\"\n", label); diff --git a/drivers/phy/phy-spear1310-miphy.c b/drivers/phy/phy-spear1310-miphy.c index 65ae640cfbd1..5f4c586ee951 100644 --- a/drivers/phy/phy-spear1310-miphy.c +++ b/drivers/phy/phy-spear1310-miphy.c @@ -192,14 +192,14 @@ static struct phy *spear1310_miphy_xlate(struct device *dev, if (args->args_count < 1) { dev_err(dev, "DT did not pass correct no of args\n"); - return ERR_PTR(-ENODEV); + return NULL; } priv->mode = args->args[0]; if (priv->mode != SATA && priv->mode != PCIE) { dev_err(dev, "DT did not pass correct phy mode\n"); - return ERR_PTR(-ENODEV); + return NULL; } return priv->phy; @@ -227,7 +227,7 @@ static int spear1310_miphy_probe(struct platform_device *pdev) return -EINVAL; } - priv->phy = devm_phy_create(dev, NULL, &spear1310_miphy_ops); + priv->phy = devm_phy_create(dev, NULL, &spear1310_miphy_ops, NULL); if (IS_ERR(priv->phy)) { dev_err(dev, "failed to create SATA PCIe PHY\n"); return PTR_ERR(priv->phy); diff --git a/drivers/phy/phy-spear1340-miphy.c b/drivers/phy/phy-spear1340-miphy.c index 1a00c2817f34..1ecd0945bad3 100644 --- a/drivers/phy/phy-spear1340-miphy.c +++ b/drivers/phy/phy-spear1340-miphy.c @@ -229,14 +229,14 @@ static struct phy *spear1340_miphy_xlate(struct device *dev, if (args->args_count < 1) { dev_err(dev, "DT did not pass correct no of args\n"); - return ERR_PTR(-ENODEV); + return NULL; } priv->mode = args->args[0]; if (priv->mode != SATA && priv->mode != PCIE) { dev_err(dev, "DT did not pass correct phy mode\n"); - return ERR_PTR(-ENODEV); + return NULL; } return priv->phy; @@ -259,7 +259,7 @@ static int spear1340_miphy_probe(struct platform_device *pdev) return PTR_ERR(priv->misc); } - priv->phy = devm_phy_create(dev, NULL, &spear1340_miphy_ops); + priv->phy = devm_phy_create(dev, NULL, &spear1340_miphy_ops, NULL); if (IS_ERR(priv->phy)) { dev_err(dev, "failed to create SATA PCIe PHY\n"); return PTR_ERR(priv->phy); diff --git a/drivers/phy/phy-stih407-usb.c b/drivers/phy/phy-stih407-usb.c index 1d5ae5f8ef69..42428d4181ea 100644 --- a/drivers/phy/phy-stih407-usb.c +++ b/drivers/phy/phy-stih407-usb.c @@ -22,9 +22,6 @@ #include #include -#define PHYPARAM_REG 1 -#define PHYCTRL_REG 2 - /* Default PHY_SEL and REFCLKSEL configuration */ #define STIH407_USB_PICOPHY_CTRL_PORT_CONF 0x6 #define STIH407_USB_PICOPHY_CTRL_PORT_MASK 0x1f @@ -96,7 +93,7 @@ static int stih407_usb2_picophy_probe(struct platform_device *pdev) struct device_node *np = dev->of_node; struct phy_provider *phy_provider; struct phy *phy; - int ret; + struct resource *res; phy_dev = devm_kzalloc(dev, sizeof(*phy_dev), GFP_KERNEL); if (!phy_dev) @@ -126,21 +123,21 @@ static int stih407_usb2_picophy_probe(struct platform_device *pdev) return PTR_ERR(phy_dev->regmap); } - ret = of_property_read_u32_index(np, "st,syscfg", PHYPARAM_REG, - &phy_dev->param); - if (ret) { - dev_err(dev, "can't get phyparam offset (%d)\n", ret); - return ret; + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctrl"); + if (!res) { + dev_err(dev, "No ctrl reg found\n"); + return -ENXIO; } + phy_dev->ctrl = res->start; - ret = of_property_read_u32_index(np, "st,syscfg", PHYCTRL_REG, - &phy_dev->ctrl); - if (ret) { - dev_err(dev, "can't get phyctrl offset (%d)\n", ret); - return ret; + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "param"); + if (!res) { + dev_err(dev, "No param reg found\n"); + return -ENXIO; } + phy_dev->param = res->start; - phy = devm_phy_create(dev, NULL, &stih407_usb2_picophy_data); + phy = devm_phy_create(dev, NULL, &stih407_usb2_picophy_data, NULL); if (IS_ERR(phy)) { dev_err(dev, "failed to create Display Port PHY\n"); return PTR_ERR(phy); diff --git a/drivers/phy/phy-stih41x-usb.c b/drivers/phy/phy-stih41x-usb.c index c093b472b57d..9f16cb8e01f4 100644 --- a/drivers/phy/phy-stih41x-usb.c +++ b/drivers/phy/phy-stih41x-usb.c @@ -87,12 +87,8 @@ static int stih41x_usb_phy_power_on(struct phy *phy) return ret; } - ret = regmap_update_bits(phy_dev->regmap, phy_dev->cfg->syscfg, - phy_dev->cfg->oscok, phy_dev->cfg->oscok); - if (ret) - clk_disable_unprepare(phy_dev->clk); - - return ret; + return regmap_update_bits(phy_dev->regmap, phy_dev->cfg->syscfg, + phy_dev->cfg->oscok, phy_dev->cfg->oscok); } static int stih41x_usb_phy_power_off(struct phy *phy) @@ -152,7 +148,7 @@ static int stih41x_usb_phy_probe(struct platform_device *pdev) return PTR_ERR(phy_dev->clk); } - phy = devm_phy_create(dev, NULL, &stih41x_usb_phy_ops); + phy = devm_phy_create(dev, NULL, &stih41x_usb_phy_ops, NULL); if (IS_ERR(phy)) { dev_err(dev, "failed to create phy\n"); @@ -164,7 +160,10 @@ static int stih41x_usb_phy_probe(struct platform_device *pdev) phy_set_drvdata(phy, phy_dev); phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); - return PTR_ERR_OR_ZERO(phy_provider); + if (IS_ERR(phy_provider)) + return PTR_ERR(phy_provider); + + return 0; } static const struct of_device_id stih41x_usb_phy_of_match[] = { diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c index a2b08f3ccb03..0baf5efc8a40 100644 --- a/drivers/phy/phy-sun4i-usb.c +++ b/drivers/phy/phy-sun4i-usb.c @@ -157,10 +157,6 @@ static int sun4i_usb_phy_init(struct phy *_phy) return ret; } - /* Enable USB 45 Ohm resistor calibration */ - if (phy->index == 0) - sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN, 0x01, 1); - /* Adjust PHY's magnitude and rate */ sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, 0x14, 5); @@ -217,7 +213,7 @@ static struct phy *sun4i_usb_phy_xlate(struct device *dev, { struct sun4i_usb_phy_data *data = dev_get_drvdata(dev); - if (args->args[0] >= data->num_phys) + if (WARN_ON(args->args[0] == 0 || args->args[0] >= data->num_phys)) return ERR_PTR(-ENODEV); return data->phys[args->args[0]].phy; @@ -244,8 +240,7 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) else data->num_phys = 3; - if (of_device_is_compatible(np, "allwinner,sun4i-a10-usb-phy") || - of_device_is_compatible(np, "allwinner,sun6i-a31-usb-phy")) + if (of_device_is_compatible(np, "allwinner,sun4i-a10-usb-phy")) data->disc_thresh = 3; else data->disc_thresh = 2; @@ -260,7 +255,8 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) if (IS_ERR(data->base)) return PTR_ERR(data->base); - for (i = 0; i < data->num_phys; i++) { + /* Skip 0, 0 is the phy for otg which is not yet supported. */ + for (i = 1; i < data->num_phys; i++) { struct sun4i_usb_phy *phy = data->phys + i; char name[16]; @@ -299,7 +295,7 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) return PTR_ERR(phy->pmu); } - phy->phy = devm_phy_create(dev, NULL, &sun4i_usb_phy_ops); + phy->phy = devm_phy_create(dev, NULL, &sun4i_usb_phy_ops, NULL); if (IS_ERR(phy->phy)) { dev_err(dev, "failed to create PHY %d\n", i); return PTR_ERR(phy->phy); diff --git a/drivers/phy/phy-sun9i-usb.c b/drivers/phy/phy-sun9i-usb.c deleted file mode 100644 index 0095914a662c..000000000000 --- a/drivers/phy/phy-sun9i-usb.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Allwinner sun9i USB phy driver - * - * Copyright (C) 2014-2015 Chen-Yu Tsai - * - * Based on phy-sun4i-usb.c from - * Hans de Goede - * - * and code from - * Allwinner Technology Co., Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define SUNXI_AHB_INCR16_BURST_EN BIT(11) -#define SUNXI_AHB_INCR8_BURST_EN BIT(10) -#define SUNXI_AHB_INCR4_BURST_EN BIT(9) -#define SUNXI_AHB_INCRX_ALIGN_EN BIT(8) -#define SUNXI_ULPI_BYPASS_EN BIT(0) - -/* usb1 HSIC specific bits */ -#define SUNXI_EHCI_HS_FORCE BIT(20) -#define SUNXI_HSIC_CONNECT_DET BIT(17) -#define SUNXI_HSIC_CONNECT_INT BIT(16) -#define SUNXI_HSIC BIT(1) - -struct sun9i_usb_phy { - struct phy *phy; - void __iomem *pmu; - struct reset_control *reset; - struct clk *clk; - struct clk *hsic_clk; - enum usb_phy_interface type; -}; - -static void sun9i_usb_phy_passby(struct sun9i_usb_phy *phy, int enable) -{ - u32 bits, reg_value; - - bits = SUNXI_AHB_INCR16_BURST_EN | SUNXI_AHB_INCR8_BURST_EN | - SUNXI_AHB_INCR4_BURST_EN | SUNXI_AHB_INCRX_ALIGN_EN | - SUNXI_ULPI_BYPASS_EN; - - if (phy->type == USBPHY_INTERFACE_MODE_HSIC) - bits |= SUNXI_HSIC | SUNXI_EHCI_HS_FORCE | - SUNXI_HSIC_CONNECT_DET | SUNXI_HSIC_CONNECT_INT; - - reg_value = readl(phy->pmu); - - if (enable) - reg_value |= bits; - else - reg_value &= ~bits; - - writel(reg_value, phy->pmu); -} - -static int sun9i_usb_phy_init(struct phy *_phy) -{ - struct sun9i_usb_phy *phy = phy_get_drvdata(_phy); - int ret; - - ret = clk_prepare_enable(phy->clk); - if (ret) - goto err_clk; - - ret = clk_prepare_enable(phy->hsic_clk); - if (ret) - goto err_hsic_clk; - - ret = reset_control_deassert(phy->reset); - if (ret) - goto err_reset; - - sun9i_usb_phy_passby(phy, 1); - return 0; - -err_reset: - clk_disable_unprepare(phy->hsic_clk); - -err_hsic_clk: - clk_disable_unprepare(phy->clk); - -err_clk: - return ret; -} - -static int sun9i_usb_phy_exit(struct phy *_phy) -{ - struct sun9i_usb_phy *phy = phy_get_drvdata(_phy); - - sun9i_usb_phy_passby(phy, 0); - reset_control_assert(phy->reset); - clk_disable_unprepare(phy->hsic_clk); - clk_disable_unprepare(phy->clk); - - return 0; -} - -static struct phy_ops sun9i_usb_phy_ops = { - .init = sun9i_usb_phy_init, - .exit = sun9i_usb_phy_exit, - .owner = THIS_MODULE, -}; - -static int sun9i_usb_phy_probe(struct platform_device *pdev) -{ - struct sun9i_usb_phy *phy; - struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; - struct phy_provider *phy_provider; - struct resource *res; - - phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); - if (!phy) - return -ENOMEM; - - phy->type = of_usb_get_phy_mode(np); - if (phy->type == USBPHY_INTERFACE_MODE_HSIC) { - phy->clk = devm_clk_get(dev, "hsic_480M"); - if (IS_ERR(phy->clk)) { - dev_err(dev, "failed to get hsic_480M clock\n"); - return PTR_ERR(phy->clk); - } - - phy->hsic_clk = devm_clk_get(dev, "hsic_12M"); - if (IS_ERR(phy->clk)) { - dev_err(dev, "failed to get hsic_12M clock\n"); - return PTR_ERR(phy->clk); - } - - phy->reset = devm_reset_control_get(dev, "hsic"); - if (IS_ERR(phy->reset)) { - dev_err(dev, "failed to get reset control\n"); - return PTR_ERR(phy->reset); - } - } else { - phy->clk = devm_clk_get(dev, "phy"); - if (IS_ERR(phy->clk)) { - dev_err(dev, "failed to get phy clock\n"); - return PTR_ERR(phy->clk); - } - - phy->reset = devm_reset_control_get(dev, "phy"); - if (IS_ERR(phy->reset)) { - dev_err(dev, "failed to get reset control\n"); - return PTR_ERR(phy->reset); - } - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - phy->pmu = devm_ioremap_resource(dev, res); - if (IS_ERR(phy->pmu)) - return PTR_ERR(phy->pmu); - - phy->phy = devm_phy_create(dev, NULL, &sun9i_usb_phy_ops); - if (IS_ERR(phy->phy)) { - dev_err(dev, "failed to create PHY\n"); - return PTR_ERR(phy->phy); - } - - phy_set_drvdata(phy->phy, phy); - phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); - - return PTR_ERR_OR_ZERO(phy_provider); -} - -static const struct of_device_id sun9i_usb_phy_of_match[] = { - { .compatible = "allwinner,sun9i-a80-usb-phy" }, - { }, -}; -MODULE_DEVICE_TABLE(of, sun9i_usb_phy_of_match); - -static struct platform_driver sun9i_usb_phy_driver = { - .probe = sun9i_usb_phy_probe, - .driver = { - .of_match_table = sun9i_usb_phy_of_match, - .name = "sun9i-usb-phy", - } -}; -module_platform_driver(sun9i_usb_phy_driver); - -MODULE_DESCRIPTION("Allwinner sun9i USB phy driver"); -MODULE_AUTHOR("Chen-Yu Tsai "); -MODULE_LICENSE("GPL"); diff --git a/drivers/phy/phy-ti-pipe3.c b/drivers/phy/phy-ti-pipe3.c index ad3fbc80e044..ab1e22d9a1e8 100644 --- a/drivers/phy/phy-ti-pipe3.c +++ b/drivers/phy/phy-ti-pipe3.c @@ -28,7 +28,6 @@ #include #include #include -#include #define PLL_STATUS 0x00000004 #define PLL_GO 0x00000008 @@ -83,10 +82,7 @@ struct ti_pipe3 { struct clk *refclk; struct clk *div_clk; struct pipe3_dpll_map *dpll_map; - bool enabled; - spinlock_t lock; /* serialize clock enable/disable */ - /* the below flag is needed specifically for SATA */ - bool refclk_enabled; + u8 id; }; static struct pipe3_dpll_map dpll_map_usb[] = { @@ -221,13 +217,8 @@ static int ti_pipe3_init(struct phy *x) u32 val; int ret = 0; - /* - * Set pcie_pcs register to 0x96 for proper functioning of phy - * as recommended in AM572x TRM SPRUHZ6, section 18.5.2.2, table - * 18-1804. - */ if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie")) { - omap_control_pcie_pcs(phy->control_dev, 0x96); + omap_control_pcie_pcs(phy->control_dev, phy->id, 0xF1); return 0; } @@ -291,7 +282,9 @@ static struct phy_ops ops = { .owner = THIS_MODULE, }; +#ifdef CONFIG_OF static const struct of_device_id ti_pipe3_id_table[]; +#endif static int ti_pipe3_probe(struct platform_device *pdev) { @@ -310,10 +303,10 @@ static int ti_pipe3_probe(struct platform_device *pdev) return -ENOMEM; phy->dev = &pdev->dev; - spin_lock_init(&phy->lock); if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie")) { - match = of_match_device(ti_pipe3_id_table, &pdev->dev); + match = of_match_device(of_match_ptr(ti_pipe3_id_table), + &pdev->dev); if (!match) return -EINVAL; @@ -336,27 +329,26 @@ static int ti_pipe3_probe(struct platform_device *pdev) } } - phy->refclk = devm_clk_get(phy->dev, "refclk"); - if (IS_ERR(phy->refclk)) { - dev_err(&pdev->dev, "unable to get refclk\n"); - /* older DTBs have missing refclk in SATA PHY - * so don't bail out in case of SATA PHY. - */ - if (!of_device_is_compatible(node, "ti,phy-pipe3-sata")) - return PTR_ERR(phy->refclk); - } - if (!of_device_is_compatible(node, "ti,phy-pipe3-sata")) { phy->wkupclk = devm_clk_get(phy->dev, "wkupclk"); if (IS_ERR(phy->wkupclk)) { dev_err(&pdev->dev, "unable to get wkupclk\n"); return PTR_ERR(phy->wkupclk); } + + phy->refclk = devm_clk_get(phy->dev, "refclk"); + if (IS_ERR(phy->refclk)) { + dev_err(&pdev->dev, "unable to get refclk\n"); + return PTR_ERR(phy->refclk); + } } else { phy->wkupclk = ERR_PTR(-ENODEV); + phy->refclk = ERR_PTR(-ENODEV); } if (of_device_is_compatible(node, "ti,phy-pipe3-pcie")) { + if (of_property_read_u8(node, "id", &phy->id) < 0) + phy->id = 1; clk = devm_clk_get(phy->dev, "dpll_ref"); if (IS_ERR(clk)) { @@ -407,7 +399,7 @@ static int ti_pipe3_probe(struct platform_device *pdev) platform_set_drvdata(pdev, phy); pm_runtime_enable(phy->dev); - generic_phy = devm_phy_create(phy->dev, NULL, &ops); + generic_phy = devm_phy_create(phy->dev, NULL, &ops, NULL); if (IS_ERR(generic_phy)) return PTR_ERR(generic_phy); @@ -431,43 +423,34 @@ static int ti_pipe3_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM -static int ti_pipe3_enable_refclk(struct ti_pipe3 *phy) -{ - if (!IS_ERR(phy->refclk) && !phy->refclk_enabled) { - int ret; - - ret = clk_prepare_enable(phy->refclk); - if (ret) { - dev_err(phy->dev, "Failed to enable refclk %d\n", ret); - return ret; - } - phy->refclk_enabled = true; - } +#ifdef CONFIG_PM_RUNTIME - return 0; -} - -static void ti_pipe3_disable_refclk(struct ti_pipe3 *phy) +static int ti_pipe3_runtime_suspend(struct device *dev) { + struct ti_pipe3 *phy = dev_get_drvdata(dev); + + if (!IS_ERR(phy->wkupclk)) + clk_disable_unprepare(phy->wkupclk); if (!IS_ERR(phy->refclk)) clk_disable_unprepare(phy->refclk); + if (!IS_ERR(phy->div_clk)) + clk_disable_unprepare(phy->div_clk); - phy->refclk_enabled = false; + return 0; } -static int ti_pipe3_enable_clocks(struct ti_pipe3 *phy) +static int ti_pipe3_runtime_resume(struct device *dev) { - int ret = 0; - unsigned long flags; - - spin_lock_irqsave(&phy->lock, flags); - if (phy->enabled) - goto err1; + u32 ret = 0; + struct ti_pipe3 *phy = dev_get_drvdata(dev); - ret = ti_pipe3_enable_refclk(phy); - if (ret) - goto err1; + if (!IS_ERR(phy->refclk)) { + ret = clk_prepare_enable(phy->refclk); + if (ret) { + dev_err(phy->dev, "Failed to enable refclk %d\n", ret); + goto err1; + } + } if (!IS_ERR(phy->wkupclk)) { ret = clk_prepare_enable(phy->wkupclk); @@ -484,9 +467,6 @@ static int ti_pipe3_enable_clocks(struct ti_pipe3 *phy) goto err3; } } - - phy->enabled = true; - spin_unlock_irqrestore(&phy->lock, flags); return 0; err3: @@ -497,80 +477,21 @@ err2: if (!IS_ERR(phy->refclk)) clk_disable_unprepare(phy->refclk); - ti_pipe3_disable_refclk(phy); err1: - spin_unlock_irqrestore(&phy->lock, flags); - return ret; -} - -static void ti_pipe3_disable_clocks(struct ti_pipe3 *phy) -{ - unsigned long flags; - - spin_lock_irqsave(&phy->lock, flags); - if (!phy->enabled) { - spin_unlock_irqrestore(&phy->lock, flags); - return; - } - - if (!IS_ERR(phy->wkupclk)) - clk_disable_unprepare(phy->wkupclk); - /* Don't disable refclk for SATA PHY due to Errata i783 */ - if (!of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata")) - ti_pipe3_disable_refclk(phy); - if (!IS_ERR(phy->div_clk)) - clk_disable_unprepare(phy->div_clk); - phy->enabled = false; - spin_unlock_irqrestore(&phy->lock, flags); -} - -static int ti_pipe3_runtime_suspend(struct device *dev) -{ - struct ti_pipe3 *phy = dev_get_drvdata(dev); - - ti_pipe3_disable_clocks(phy); - return 0; -} - -static int ti_pipe3_runtime_resume(struct device *dev) -{ - struct ti_pipe3 *phy = dev_get_drvdata(dev); - int ret = 0; - - ret = ti_pipe3_enable_clocks(phy); return ret; } -static int ti_pipe3_suspend(struct device *dev) -{ - struct ti_pipe3 *phy = dev_get_drvdata(dev); - - ti_pipe3_disable_clocks(phy); - return 0; -} - -static int ti_pipe3_resume(struct device *dev) -{ - struct ti_pipe3 *phy = dev_get_drvdata(dev); - int ret; - - ret = ti_pipe3_enable_clocks(phy); - if (ret) - return ret; - - pm_runtime_disable(dev); - pm_runtime_set_active(dev); - pm_runtime_enable(dev); - return 0; -} -#endif - static const struct dev_pm_ops ti_pipe3_pm_ops = { SET_RUNTIME_PM_OPS(ti_pipe3_runtime_suspend, ti_pipe3_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(ti_pipe3_suspend, ti_pipe3_resume) }; +#define DEV_PM_OPS (&ti_pipe3_pm_ops) +#else +#define DEV_PM_OPS NULL +#endif + +#ifdef CONFIG_OF static const struct of_device_id ti_pipe3_id_table[] = { { .compatible = "ti,phy-usb3", @@ -590,14 +511,15 @@ static const struct of_device_id ti_pipe3_id_table[] = { {} }; MODULE_DEVICE_TABLE(of, ti_pipe3_id_table); +#endif static struct platform_driver ti_pipe3_driver = { .probe = ti_pipe3_probe, .remove = ti_pipe3_remove, .driver = { .name = "ti-pipe3", - .pm = &ti_pipe3_pm_ops, - .of_match_table = ti_pipe3_id_table, + .pm = DEV_PM_OPS, + .of_match_table = of_match_ptr(ti_pipe3_id_table), }, }; diff --git a/drivers/phy/phy-twl4030-usb.c b/drivers/phy/phy-twl4030-usb.c index 8e87f54671f3..e2698d29f436 100644 --- a/drivers/phy/phy-twl4030-usb.c +++ b/drivers/phy/phy-twl4030-usb.c @@ -644,6 +644,7 @@ static int twl4030_usb_probe(struct platform_device *pdev) struct usb_otg *otg; struct device_node *np = pdev->dev.of_node; struct phy_provider *phy_provider; + struct phy_init_data *init_data = NULL; twl = devm_kzalloc(&pdev->dev, sizeof(*twl), GFP_KERNEL); if (!twl) @@ -654,6 +655,7 @@ static int twl4030_usb_probe(struct platform_device *pdev) (enum twl4030_usb_mode *)&twl->usb_mode); else if (pdata) { twl->usb_mode = pdata->usb_mode; + init_data = pdata->init_data; } else { dev_err(&pdev->dev, "twl4030 initialized without pdata\n"); return -EINVAL; @@ -678,7 +680,7 @@ static int twl4030_usb_probe(struct platform_device *pdev) otg->set_host = twl4030_set_host; otg->set_peripheral = twl4030_set_peripheral; - phy = devm_phy_create(twl->dev, NULL, &ops); + phy = devm_phy_create(twl->dev, NULL, &ops, init_data); if (IS_ERR(phy)) { dev_dbg(&pdev->dev, "Failed to create PHY\n"); return PTR_ERR(phy); @@ -731,11 +733,6 @@ static int twl4030_usb_probe(struct platform_device *pdev) return status; } - if (pdata) - err = phy_create_lookup(phy, "usb", "musb-hdrc.0"); - if (err) - return err; - pm_runtime_mark_last_busy(&pdev->dev); pm_runtime_put_autosuspend(twl->dev); diff --git a/drivers/phy/phy-xgene.c b/drivers/phy/phy-xgene.c index bae9cccc08f0..f8a51b16ade8 100644 --- a/drivers/phy/phy-xgene.c +++ b/drivers/phy/phy-xgene.c @@ -1657,6 +1657,7 @@ static int xgene_phy_probe(struct platform_device *pdev) struct phy_provider *phy_provider; struct xgene_phy_ctx *ctx; struct resource *res; + int rc = 0; u32 default_spd[] = DEFAULT_SATA_SPD_SEL; u32 default_txboost_gain[] = DEFAULT_SATA_TXBOOST_GAIN; u32 default_txeye_direction[] = DEFAULT_SATA_TXEYEDIRECTION; @@ -1675,8 +1676,10 @@ static int xgene_phy_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ctx->sds_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(ctx->sds_base)) - return PTR_ERR(ctx->sds_base); + if (IS_ERR(ctx->sds_base)) { + rc = PTR_ERR(ctx->sds_base); + goto error; + } /* Retrieve optional clock */ ctx->clk = clk_get(&pdev->dev, NULL); @@ -1704,15 +1707,25 @@ static int xgene_phy_probe(struct platform_device *pdev) ctx->dev = &pdev->dev; platform_set_drvdata(pdev, ctx); - ctx->phy = devm_phy_create(ctx->dev, NULL, &xgene_phy_ops); + ctx->phy = devm_phy_create(ctx->dev, NULL, &xgene_phy_ops, NULL); if (IS_ERR(ctx->phy)) { dev_dbg(&pdev->dev, "Failed to create PHY\n"); - return PTR_ERR(ctx->phy); + rc = PTR_ERR(ctx->phy); + goto error; } phy_set_drvdata(ctx->phy, ctx); - phy_provider = devm_of_phy_provider_register(ctx->dev, xgene_phy_xlate); - return PTR_ERR_OR_ZERO(phy_provider); + phy_provider = devm_of_phy_provider_register(ctx->dev, + xgene_phy_xlate); + if (IS_ERR(phy_provider)) { + rc = PTR_ERR(phy_provider); + goto error; + } + + return 0; + +error: + return rc; } static const struct of_device_id xgene_phy_of_match[] = { diff --git a/include/linux/phy/omap_control_phy.h b/include/linux/phy/omap_control_phy.h index eb7d4a135a9e..e9e6cfbfbb58 100644 --- a/include/linux/phy/omap_control_phy.h +++ b/include/linux/phy/omap_control_phy.h @@ -66,7 +66,7 @@ enum omap_control_usb_mode { #define OMAP_CTRL_PIPE3_PHY_TX_RX_POWEROFF 0x0 #define OMAP_CTRL_PCIE_PCS_MASK 0xff -#define OMAP_CTRL_PCIE_PCS_DELAY_COUNT_SHIFT 16 +#define OMAP_CTRL_PCIE_PCS_DELAY_COUNT_SHIFT 0x8 #define OMAP_CTRL_USB2_PHY_PD BIT(28) @@ -79,7 +79,7 @@ enum omap_control_usb_mode { void omap_control_phy_power(struct device *dev, int on); void omap_control_usb_set_mode(struct device *dev, enum omap_control_usb_mode mode); -void omap_control_pcie_pcs(struct device *dev, u8 delay); +void omap_control_pcie_pcs(struct device *dev, u8 id, u8 delay); #else static inline void omap_control_phy_power(struct device *dev, int on) @@ -91,7 +91,7 @@ static inline void omap_control_usb_set_mode(struct device *dev, { } -static inline void omap_control_pcie_pcs(struct device *dev, u8 delay) +static inline void omap_control_pcie_pcs(struct device *dev, u8 id, u8 delay) { } #endif diff --git a/include/linux/phy/phy-qcom-ufs.h b/include/linux/phy/phy-qcom-ufs.h deleted file mode 100644 index 9d18e9f948e9..000000000000 --- a/include/linux/phy/phy-qcom-ufs.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2013-2015, Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#ifndef PHY_QCOM_UFS_H_ -#define PHY_QCOM_UFS_H_ - -#include "phy.h" - -/** - * ufs_qcom_phy_enable_ref_clk() - Enable the phy - * ref clock. - * @phy: reference to a generic phy - * - * returns 0 for success, and non-zero for error. - */ -int ufs_qcom_phy_enable_ref_clk(struct phy *phy); - -/** - * ufs_qcom_phy_disable_ref_clk() - Disable the phy - * ref clock. - * @phy: reference to a generic phy. - */ -void ufs_qcom_phy_disable_ref_clk(struct phy *phy); - -/** - * ufs_qcom_phy_enable_dev_ref_clk() - Enable the device - * ref clock. - * @phy: reference to a generic phy. - */ -void ufs_qcom_phy_enable_dev_ref_clk(struct phy *phy); - -/** - * ufs_qcom_phy_disable_dev_ref_clk() - Disable the device - * ref clock. - * @phy: reference to a generic phy. - */ -void ufs_qcom_phy_disable_dev_ref_clk(struct phy *phy); - -int ufs_qcom_phy_enable_iface_clk(struct phy *phy); -void ufs_qcom_phy_disable_iface_clk(struct phy *phy); -int ufs_qcom_phy_start_serdes(struct phy *phy); -int ufs_qcom_phy_set_tx_lane_enable(struct phy *phy, u32 tx_lanes); -int ufs_qcom_phy_calibrate_phy(struct phy *phy, bool is_rate_B); -int ufs_qcom_phy_is_pcs_ready(struct phy *phy); -void ufs_qcom_phy_save_controller_version(struct phy *phy, - u8 major, u16 minor, u16 step); - -#endif /* PHY_QCOM_UFS_H_ */ diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h index a0197fa1b116..8cb6f815475b 100644 --- a/include/linux/phy/phy.h +++ b/include/linux/phy/phy.h @@ -61,6 +61,7 @@ struct phy { struct device dev; int id; const struct phy_ops *ops; + struct phy_init_data *init_data; struct mutex mutex; int init_count; int power_count; @@ -83,14 +84,33 @@ struct phy_provider { struct of_phandle_args *args); }; -struct phy_lookup { - struct list_head node; - const char *dev_id; - const char *con_id; - struct phy *phy; +/** + * struct phy_consumer - represents the phy consumer + * @dev_name: the device name of the controller that will use this PHY device + * @port: name given to the consumer port + */ +struct phy_consumer { + const char *dev_name; + const char *port; +}; + +/** + * struct phy_init_data - contains the list of PHY consumers + * @num_consumers: number of consumers for this PHY device + * @consumers: list of PHY consumers + */ +struct phy_init_data { + unsigned int num_consumers; + struct phy_consumer *consumers; }; -#define to_phy(a) (container_of((a), struct phy, dev)) +#define PHY_CONSUMER(_dev_name, _port) \ +{ \ + .dev_name = _dev_name, \ + .port = _port, \ +} + +#define to_phy(dev) (container_of((dev), struct phy, dev)) #define of_phy_provider_register(dev, xlate) \ __of_phy_provider_register((dev), THIS_MODULE, (xlate)) @@ -139,9 +159,10 @@ struct phy *of_phy_get(struct device_node *np, const char *con_id); struct phy *of_phy_simple_xlate(struct device *dev, struct of_phandle_args *args); struct phy *phy_create(struct device *dev, struct device_node *node, - const struct phy_ops *ops); + const struct phy_ops *ops, + struct phy_init_data *init_data); struct phy *devm_phy_create(struct device *dev, struct device_node *node, - const struct phy_ops *ops); + const struct phy_ops *ops, struct phy_init_data *init_data); void phy_destroy(struct phy *phy); void devm_phy_destroy(struct device *dev, struct phy *phy); struct phy_provider *__of_phy_provider_register(struct device *dev, @@ -153,8 +174,6 @@ struct phy_provider *__devm_of_phy_provider_register(struct device *dev, void of_phy_provider_unregister(struct phy_provider *phy_provider); void devm_of_phy_provider_unregister(struct device *dev, struct phy_provider *phy_provider); -int phy_create_lookup(struct phy *phy, const char *con_id, const char *dev_id); -void phy_remove_lookup(struct phy *phy, const char *con_id, const char *dev_id); #else static inline int phy_pm_runtime_get(struct phy *phy) { @@ -282,14 +301,16 @@ static inline struct phy *of_phy_simple_xlate(struct device *dev, static inline struct phy *phy_create(struct device *dev, struct device_node *node, - const struct phy_ops *ops) + const struct phy_ops *ops, + struct phy_init_data *init_data) { return ERR_PTR(-ENOSYS); } static inline struct phy *devm_phy_create(struct device *dev, struct device_node *node, - const struct phy_ops *ops) + const struct phy_ops *ops, + struct phy_init_data *init_data) { return ERR_PTR(-ENOSYS); } @@ -324,13 +345,6 @@ static inline void devm_of_phy_provider_unregister(struct device *dev, struct phy_provider *phy_provider) { } -static inline int -phy_create_lookup(struct phy *phy, const char *con_id, const char *dev_id) -{ - return 0; -} -static inline void phy_remove_lookup(struct phy *phy, const char *con_id, - const char *dev_id) { } #endif #endif /* __DRIVERS_PHY_H */