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
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
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
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
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
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
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
#
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
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
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
+++ /dev/null
-/*
- * USB cluster support for Armada 375 platform.
- *
- * Copyright (C) 2014 Marvell
- *
- * Gregory CLEMENT <gregory.clement@free-electrons.com>
- *
- * 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 <dt-bindings/phy/phy.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of_address.h>
-#include <linux/phy/phy.h>
-#include <linux/platform_device.h>
-
-#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 <gregory.clement@free-electrons.com>");
-MODULE_LICENSE("GPL");
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);
#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)
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);
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);
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);
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);
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" },
{ },
};
+++ /dev/null
-/*
- * Copyright (C) 2014 Marvell Technology Group Ltd.
- *
- * Antoine Tenart <antoine.tenart@free-electrons.com>
- * Jisheng Zhang <jszhang@marvell.com>
- *
- * 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 <linux/gpio.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/of_device.h>
-#include <linux/of_gpio.h>
-#include <linux/phy/phy.h>
-#include <linux/platform_device.h>
-#include <linux/reset.h>
-
-#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 <antoine.tenart@free-electrons.com>");
-MODULE_DESCRIPTION("Marvell Berlin PHY driver for USB");
-MODULE_LICENSE("GPL");
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)
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)
{
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;
}
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;
* @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;
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)
* @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.
* 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;
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);
+++ /dev/null
-/*
- * 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 <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/regmap.h>
-
-#include <linux/slab.h>
-#include <linux/of.h>
-#include <linux/io.h>
-#include <linux/usb/phy_companion.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/pm_runtime.h>
-#include <linux/delay.h>
-#include <linux/phy/phy.h>
-#include <linux/of_platform.h>
-
-#include <linux/mfd/syscon.h>
-
-/*
- * 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 <tony@atomide.com>");
-MODULE_DESCRIPTION("dm816x usb phy driver");
-MODULE_LICENSE("GPL v2");
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);
#include <linux/err.h>
#include <linux/io.h>
#include <linux/kernel.h>
-#include <linux/mfd/syscon/exynos4-pmu.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
-#include <linux/regmap.h>
#include <linux/spinlock.h>
-#include <linux/mfd/syscon.h>
-/* 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,
((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;
}
{
struct exynos_mipi_video_phy *state;
struct device *dev = &pdev->dev;
+ struct resource *res;
struct phy_provider *phy_provider;
unsigned int i;
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);
const struct exynos5_usbdrd_phy_config *phy_cfg;
u32 pmu_offset_usbdrd0_phy;
u32 pmu_offset_usbdrd1_phy;
- bool has_common_clk_gate;
};
/**
* @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'.
* 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;
u32 extrefclk;
struct clk *ref_clk;
struct regulator *vbus;
- struct regulator *vbus_boost;
};
static inline
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;
}
}
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;
}
/* 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;
}
.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,
.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[] = {
}, {
.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
},
{ },
};
const struct exynos5_usbdrd_phy_drvdata *drv_data;
struct regmap *reg_pmu;
u32 pmu_offset;
+ unsigned long ref_rate;
int i, ret;
int channel;
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;
}
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);
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);
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");
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);
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[] = {
+++ /dev/null
-/*
- * Copyright (C) 2014 STMicroelectronics
- *
- * STMicroelectronics PHY driver MiPHY28lp (for SoC STiH407).
- *
- * Author: Alexandre Torgue <alexandre.torgue@st.com>
- *
- * 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 <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/of_address.h>
-#include <linux/clk.h>
-#include <linux/phy/phy.h>
-#include <linux/delay.h>
-#include <linux/mfd/syscon.h>
-#include <linux/regmap.h>
-#include <linux/reset.h>
-
-#include <dt-bindings/phy/phy.h>
-
-/* 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 <alexandre.torgue@st.com>");
-MODULE_DESCRIPTION("STMicroelectronics miphy28lp driver");
-MODULE_LICENSE("GPL v2");
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
-#include <dt-bindings/phy/phy.h>
+#include <dt-bindings/phy/phy-miphy365x.h>
#define HFC_TIMEOUT 100
bool pcie_tx_pol_inv;
bool sata_tx_pol_inv;
u32 sata_gen;
- u32 ctrlreg;
+ u64 ctrlreg;
u8 type;
};
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);
}
}
/* 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);
{
struct device_node *phynode = miphy_phy->phy->dev.of_node;
const char *name;
+ const __be32 *taddr;
int type = miphy_phy->type;
int ret;
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);
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);
}
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);
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[] = {
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);
/**
* 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;
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);
return;
ctrl_phy = dev_get_drvdata(dev);
+
if (!ctrl_phy) {
dev_err(dev, "Invalid control phy device\n");
return;
}
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;
{},
};
MODULE_DEVICE_TABLE(of, omap_control_phy_id_table);
+#endif
+
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;
.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),
},
};
.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,
{},
};
MODULE_DEVICE_TABLE(of, omap_usb2_id_table);
+#endif
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;
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);
return 0;
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_RUNTIME
static int omap_usb2_runtime_suspend(struct device *dev)
{
.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),
},
};
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);
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);
+++ /dev/null
-/*
- * 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 <linux/module.h>
-#include <linux/clk.h>
-#include <linux/regulator/consumer.h>
-#include <linux/slab.h>
-#include <linux/phy/phy-qcom-ufs.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-
-#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
+++ /dev/null
-/*
- * 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");
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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");
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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);
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);
/*
* Rockchip usb PHY driver
*
- * Copyright (C) 2014 Yunzhi Li <lyz@rock-chips.com>
+ * Copyright (C) 2014 Roy Li <lyz@rock-chips.com>
* Copyright (C) 2014 ROCKCHIP, Inc.
*
* This program is free software; you can redistribute it and/or modify
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
-/*
- * 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)
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;
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;
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,
{
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)) {
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[] = {
module_platform_driver(rockchip_usb_driver);
-MODULE_AUTHOR("Yunzhi Li <lyz@rock-chips.com>");
+MODULE_AUTHOR("Roy Li <lyz@rock-chips.com>");
MODULE_DESCRIPTION("Rockchip USB 2.0 PHY driver");
MODULE_LICENSE("GPL v2");
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:
{
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);
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 = {
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);
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;
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);
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;
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);
#include <linux/mfd/syscon.h>
#include <linux/phy/phy.h>
-#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
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)
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);
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)
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");
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[] = {
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);
{
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;
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;
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];
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);
+++ /dev/null
-/*
- * Allwinner sun9i USB phy driver
- *
- * Copyright (C) 2014-2015 Chen-Yu Tsai <wens@csie.org>
- *
- * Based on phy-sun4i-usb.c from
- * Hans de Goede <hdegoede@redhat.com>
- *
- * and code from
- * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
- *
- * 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 <linux/clk.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/phy/phy.h>
-#include <linux/usb/of.h>
-#include <linux/platform_device.h>
-#include <linux/reset.h>
-
-#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 <wens@csie.org>");
-MODULE_LICENSE("GPL");
#include <linux/delay.h>
#include <linux/phy/omap_control_phy.h>
#include <linux/of_platform.h>
-#include <linux/spinlock.h>
#define PLL_STATUS 0x00000004
#define PLL_GO 0x00000008
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[] = {
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;
}
.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)
{
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;
}
}
- 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)) {
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);
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);
goto err3;
}
}
-
- phy->enabled = true;
- spin_unlock_irqrestore(&phy->lock, flags);
return 0;
err3:
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",
{}
};
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),
},
};
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)
(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;
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);
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);
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;
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);
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[] = {
#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)
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)
{
}
-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
+++ /dev/null
-/*
- * 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_ */
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;
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))
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,
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)
{
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);
}
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 */