diff --git a/Documentation/devicetree/bindings/ufs/ufs-msm.txt b/Documentation/devicetree/bindings/ufs/ufs-msm.txt deleted file mode 100644 index 1b54b3c50ef3..000000000000 --- a/Documentation/devicetree/bindings/ufs/ufs-msm.txt +++ /dev/null @@ -1,41 +0,0 @@ -* MSM Universal Flash Storage (UFS) PHY - -UFSPHY nodes are defined to describe on-chip UFS PHY hardware macro. -Each UFS PHY node should have its own node. - -To bind UFS PHY with UFS host controller, the controller node should -contain a phandle reference to UFS PHY node. - -Required properties: -- compatible : compatible list, contains "qcom,ufs-phy-qmp-28nm" - or "qcom,ufs-phy-qmp-20nm" according to the relevant - phy in use -- reg : should contain PHY register address space (mandatory), - device PHY control register map (optional). -- reg-names : indicates various resources passed to driver (via reg proptery) by name. - Required "reg-names" is "phy_mem" and "dev_ref_clk_ctrl_mem" is optional. -- #phy-cells : This property shall be set to 0 -- vdda-phy-supply : phandle to main PHY supply for analog domain -- vdda-pll-supply : phandle to PHY PLL and Power-Gen block power supply - -Optional properties: -- vdda-phy-max-microamp : specifies max. load that can be drawn from phy supply -- vdda-pll-max-microamp : specifies max. load that can be drawn from pll supply - -Example: - - ufsphy1: ufsphy@0xfc597000 { - compatible = "qcom,ufs-phy-qmp-28nm"; - reg = <0xfc597000 0x800>, <0xfd512074 0x4>; - reg-names = "phy_mem", "dev_ref_clk_ctrl_mem"; - #phy-cells = <0>; - vdda-phy-supply = <&pma8084_l4>; - vdda-pll-supply = <&pma8084_l12>; - vdda-phy-max-microamp = <50000>; - vdda-pll-max-microamp = <1000>; - }; - - ufshc@0xfc598000 { - ... - phys = <&ufsphy1>; - }; diff --git a/drivers/phy/phy-qcom-ufs-qmp-20nm.c~HEAD b/drivers/phy/phy-qcom-ufs-qmp-20nm.c~HEAD deleted file mode 100644 index b16ea77d07b9..000000000000 --- a/drivers/phy/phy-qcom-ufs-qmp-20nm.c~HEAD +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright (c) 2013-2015, Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include "phy-qcom-ufs-qmp-20nm.h" - -#define UFS_PHY_NAME "ufs_phy_qmp_20nm" - -static -int ufs_qcom_phy_qmp_20nm_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy, - bool is_rate_B) -{ - struct ufs_qcom_phy_calibration *tbl_A, *tbl_B; - int tbl_size_A, tbl_size_B; - u8 major = ufs_qcom_phy->host_ctrl_rev_major; - u16 minor = ufs_qcom_phy->host_ctrl_rev_minor; - u16 step = ufs_qcom_phy->host_ctrl_rev_step; - int err; - - if ((major == 0x1) && (minor == 0x002) && (step == 0x0000)) { - tbl_size_A = ARRAY_SIZE(phy_cal_table_rate_A_1_2_0); - tbl_A = phy_cal_table_rate_A_1_2_0; - } else if ((major == 0x1) && (minor == 0x003) && (step == 0x0000)) { - tbl_size_A = ARRAY_SIZE(phy_cal_table_rate_A_1_3_0); - tbl_A = phy_cal_table_rate_A_1_3_0; - } else { - dev_err(ufs_qcom_phy->dev, "%s: Unknown UFS-PHY version, no calibration values\n", - __func__); - err = -ENODEV; - goto out; - } - - tbl_size_B = ARRAY_SIZE(phy_cal_table_rate_B); - tbl_B = phy_cal_table_rate_B; - - err = ufs_qcom_phy_calibrate(ufs_qcom_phy, tbl_A, tbl_size_A, - tbl_B, tbl_size_B, is_rate_B); - - if (err) - dev_err(ufs_qcom_phy->dev, "%s: ufs_qcom_phy_calibrate() failed %d\n", - __func__, err); - -out: - return err; -} - -static -void ufs_qcom_phy_qmp_20nm_advertise_quirks(struct ufs_qcom_phy *phy_common) -{ - phy_common->quirks = - UFS_QCOM_PHY_QUIRK_HIBERN8_EXIT_AFTER_PHY_PWR_COLLAPSE; -} - -static int ufs_qcom_phy_qmp_20nm_init(struct phy *generic_phy) -{ - struct ufs_qcom_phy_qmp_20nm *phy = phy_get_drvdata(generic_phy); - struct ufs_qcom_phy *phy_common = &phy->common_cfg; - int err = 0; - - err = ufs_qcom_phy_init_clks(generic_phy, phy_common); - if (err) { - dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_clks() failed %d\n", - __func__, err); - goto out; - } - - err = ufs_qcom_phy_init_vregulators(generic_phy, phy_common); - if (err) { - dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_vregulators() failed %d\n", - __func__, err); - goto out; - } - - ufs_qcom_phy_qmp_20nm_advertise_quirks(phy_common); - -out: - return err; -} - -static -void ufs_qcom_phy_qmp_20nm_power_control(struct ufs_qcom_phy *phy, bool val) -{ - bool hibern8_exit_after_pwr_collapse = phy->quirks & - UFS_QCOM_PHY_QUIRK_HIBERN8_EXIT_AFTER_PHY_PWR_COLLAPSE; - - if (val) { - writel_relaxed(0x1, phy->mmio + UFS_PHY_POWER_DOWN_CONTROL); - /* - * Before any transactions involving PHY, ensure PHY knows - * that it's analog rail is powered ON. - */ - mb(); - - if (hibern8_exit_after_pwr_collapse) { - /* - * Give atleast 1us delay after restoring PHY analog - * power. - */ - usleep_range(1, 2); - writel_relaxed(0x0A, phy->mmio + - QSERDES_COM_SYSCLK_EN_SEL_TXBAND); - writel_relaxed(0x08, phy->mmio + - QSERDES_COM_SYSCLK_EN_SEL_TXBAND); - /* - * Make sure workaround is deactivated before proceeding - * with normal PHY operations. - */ - mb(); - } - } else { - if (hibern8_exit_after_pwr_collapse) { - writel_relaxed(0x0A, phy->mmio + - QSERDES_COM_SYSCLK_EN_SEL_TXBAND); - writel_relaxed(0x02, phy->mmio + - QSERDES_COM_SYSCLK_EN_SEL_TXBAND); - /* - * Make sure that above workaround is activated before - * PHY analog power collapse. - */ - mb(); - } - - writel_relaxed(0x0, phy->mmio + UFS_PHY_POWER_DOWN_CONTROL); - /* - * ensure that PHY knows its PHY analog rail is going - * to be powered down - */ - mb(); - } -} - -static -void ufs_qcom_phy_qmp_20nm_set_tx_lane_enable(struct ufs_qcom_phy *phy, u32 val) -{ - writel_relaxed(val & UFS_PHY_TX_LANE_ENABLE_MASK, - phy->mmio + UFS_PHY_TX_LANE_ENABLE); - mb(); -} - -static inline void ufs_qcom_phy_qmp_20nm_start_serdes(struct ufs_qcom_phy *phy) -{ - u32 tmp; - - tmp = readl_relaxed(phy->mmio + UFS_PHY_PHY_START); - tmp &= ~MASK_SERDES_START; - tmp |= (1 << OFFSET_SERDES_START); - writel_relaxed(tmp, phy->mmio + UFS_PHY_PHY_START); - mb(); -} - -static int ufs_qcom_phy_qmp_20nm_is_pcs_ready(struct ufs_qcom_phy *phy_common) -{ - int err = 0; - u32 val; - - err = readl_poll_timeout(phy_common->mmio + UFS_PHY_PCS_READY_STATUS, - val, (val & MASK_PCS_READY), 10, 1000000); - if (err) - dev_err(phy_common->dev, "%s: poll for pcs failed err = %d\n", - __func__, err); - return err; -} - -static const 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", - }, -}; - -module_platform_driver(ufs_qcom_phy_qmp_20nm_driver); - -MODULE_DESCRIPTION("Universal Flash Storage (UFS) QCOM PHY QMP 20nm"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/phy/phy-qcom-ufs-qmp-20nm.h~HEAD b/drivers/phy/phy-qcom-ufs-qmp-20nm.h~HEAD deleted file mode 100644 index 4f3076bb3d71..000000000000 --- a/drivers/phy/phy-qcom-ufs-qmp-20nm.h~HEAD +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright (c) 2013-2015, Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#ifndef UFS_QCOM_PHY_QMP_20NM_H_ -#define UFS_QCOM_PHY_QMP_20NM_H_ - -#include "phy-qcom-ufs-i.h" - -/* QCOM UFS PHY control registers */ - -#define COM_OFF(x) (0x000 + x) -#define PHY_OFF(x) (0xC00 + x) -#define TX_OFF(n, x) (0x400 + (0x400 * n) + x) -#define RX_OFF(n, x) (0x600 + (0x400 * n) + x) - -/* UFS PHY PLL block registers */ -#define QSERDES_COM_SYS_CLK_CTRL COM_OFF(0x0) -#define QSERDES_COM_PLL_VCOTAIL_EN COM_OFF(0x04) -#define QSERDES_COM_PLL_CNTRL COM_OFF(0x14) -#define QSERDES_COM_PLL_IP_SETI COM_OFF(0x24) -#define QSERDES_COM_CORE_CLK_IN_SYNC_SEL COM_OFF(0x28) -#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN COM_OFF(0x30) -#define QSERDES_COM_PLL_CP_SETI COM_OFF(0x34) -#define QSERDES_COM_PLL_IP_SETP COM_OFF(0x38) -#define QSERDES_COM_PLL_CP_SETP COM_OFF(0x3C) -#define QSERDES_COM_SYSCLK_EN_SEL_TXBAND COM_OFF(0x48) -#define QSERDES_COM_RESETSM_CNTRL COM_OFF(0x4C) -#define QSERDES_COM_RESETSM_CNTRL2 COM_OFF(0x50) -#define QSERDES_COM_PLLLOCK_CMP1 COM_OFF(0x90) -#define QSERDES_COM_PLLLOCK_CMP2 COM_OFF(0x94) -#define QSERDES_COM_PLLLOCK_CMP3 COM_OFF(0x98) -#define QSERDES_COM_PLLLOCK_CMP_EN COM_OFF(0x9C) -#define QSERDES_COM_BGTC COM_OFF(0xA0) -#define QSERDES_COM_DEC_START1 COM_OFF(0xAC) -#define QSERDES_COM_PLL_AMP_OS COM_OFF(0xB0) -#define QSERDES_COM_RES_CODE_UP_OFFSET COM_OFF(0xD8) -#define QSERDES_COM_RES_CODE_DN_OFFSET COM_OFF(0xDC) -#define QSERDES_COM_DIV_FRAC_START1 COM_OFF(0x100) -#define QSERDES_COM_DIV_FRAC_START2 COM_OFF(0x104) -#define QSERDES_COM_DIV_FRAC_START3 COM_OFF(0x108) -#define QSERDES_COM_DEC_START2 COM_OFF(0x10C) -#define QSERDES_COM_PLL_RXTXEPCLK_EN COM_OFF(0x110) -#define QSERDES_COM_PLL_CRCTRL COM_OFF(0x114) -#define QSERDES_COM_PLL_CLKEPDIV COM_OFF(0x118) - -/* TX LANE n (0, 1) registers */ -#define QSERDES_TX_EMP_POST1_LVL(n) TX_OFF(n, 0x08) -#define QSERDES_TX_DRV_LVL(n) TX_OFF(n, 0x0C) -#define QSERDES_TX_LANE_MODE(n) TX_OFF(n, 0x54) - -/* RX LANE n (0, 1) registers */ -#define QSERDES_RX_CDR_CONTROL1(n) RX_OFF(n, 0x0) -#define QSERDES_RX_CDR_CONTROL_HALF(n) RX_OFF(n, 0x8) -#define QSERDES_RX_RX_EQ_GAIN1_LSB(n) RX_OFF(n, 0xA8) -#define QSERDES_RX_RX_EQ_GAIN1_MSB(n) RX_OFF(n, 0xAC) -#define QSERDES_RX_RX_EQ_GAIN2_LSB(n) RX_OFF(n, 0xB0) -#define QSERDES_RX_RX_EQ_GAIN2_MSB(n) RX_OFF(n, 0xB4) -#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2(n) RX_OFF(n, 0xBC) -#define QSERDES_RX_CDR_CONTROL_QUARTER(n) RX_OFF(n, 0xC) -#define QSERDES_RX_SIGDET_CNTRL(n) RX_OFF(n, 0x100) - -/* UFS PHY registers */ -#define UFS_PHY_PHY_START PHY_OFF(0x00) -#define UFS_PHY_POWER_DOWN_CONTROL PHY_OFF(0x4) -#define UFS_PHY_TX_LANE_ENABLE PHY_OFF(0x44) -#define UFS_PHY_PWM_G1_CLK_DIVIDER PHY_OFF(0x08) -#define UFS_PHY_PWM_G2_CLK_DIVIDER PHY_OFF(0x0C) -#define UFS_PHY_PWM_G3_CLK_DIVIDER PHY_OFF(0x10) -#define UFS_PHY_PWM_G4_CLK_DIVIDER PHY_OFF(0x14) -#define UFS_PHY_CORECLK_PWM_G1_CLK_DIVIDER PHY_OFF(0x34) -#define UFS_PHY_CORECLK_PWM_G2_CLK_DIVIDER PHY_OFF(0x38) -#define UFS_PHY_CORECLK_PWM_G3_CLK_DIVIDER PHY_OFF(0x3C) -#define UFS_PHY_CORECLK_PWM_G4_CLK_DIVIDER PHY_OFF(0x40) -#define UFS_PHY_OMC_STATUS_RDVAL PHY_OFF(0x68) -#define UFS_PHY_LINE_RESET_TIME PHY_OFF(0x28) -#define UFS_PHY_LINE_RESET_GRANULARITY PHY_OFF(0x2C) -#define UFS_PHY_TSYNC_RSYNC_CNTL PHY_OFF(0x48) -#define UFS_PHY_PLL_CNTL PHY_OFF(0x50) -#define UFS_PHY_TX_LARGE_AMP_DRV_LVL PHY_OFF(0x54) -#define UFS_PHY_TX_SMALL_AMP_DRV_LVL PHY_OFF(0x5C) -#define UFS_PHY_TX_LARGE_AMP_POST_EMP_LVL PHY_OFF(0x58) -#define UFS_PHY_TX_SMALL_AMP_POST_EMP_LVL PHY_OFF(0x60) -#define UFS_PHY_CFG_CHANGE_CNT_VAL PHY_OFF(0x64) -#define UFS_PHY_RX_SYNC_WAIT_TIME PHY_OFF(0x6C) -#define UFS_PHY_TX_MIN_SLEEP_NOCONFIG_TIME_CAPABILITY PHY_OFF(0xB4) -#define UFS_PHY_RX_MIN_SLEEP_NOCONFIG_TIME_CAPABILITY PHY_OFF(0xE0) -#define UFS_PHY_TX_MIN_STALL_NOCONFIG_TIME_CAPABILITY PHY_OFF(0xB8) -#define UFS_PHY_RX_MIN_STALL_NOCONFIG_TIME_CAPABILITY PHY_OFF(0xE4) -#define UFS_PHY_TX_MIN_SAVE_CONFIG_TIME_CAPABILITY PHY_OFF(0xBC) -#define UFS_PHY_RX_MIN_SAVE_CONFIG_TIME_CAPABILITY PHY_OFF(0xE8) -#define UFS_PHY_RX_PWM_BURST_CLOSURE_LENGTH_CAPABILITY PHY_OFF(0xFC) -#define UFS_PHY_RX_MIN_ACTIVATETIME_CAPABILITY PHY_OFF(0x100) -#define UFS_PHY_RX_SIGDET_CTRL3 PHY_OFF(0x14c) -#define UFS_PHY_RMMI_ATTR_CTRL PHY_OFF(0x160) -#define UFS_PHY_RMMI_RX_CFGUPDT_L1 (1 << 7) -#define UFS_PHY_RMMI_TX_CFGUPDT_L1 (1 << 6) -#define UFS_PHY_RMMI_CFGWR_L1 (1 << 5) -#define UFS_PHY_RMMI_CFGRD_L1 (1 << 4) -#define UFS_PHY_RMMI_RX_CFGUPDT_L0 (1 << 3) -#define UFS_PHY_RMMI_TX_CFGUPDT_L0 (1 << 2) -#define UFS_PHY_RMMI_CFGWR_L0 (1 << 1) -#define UFS_PHY_RMMI_CFGRD_L0 (1 << 0) -#define UFS_PHY_RMMI_ATTRID PHY_OFF(0x164) -#define UFS_PHY_RMMI_ATTRWRVAL PHY_OFF(0x168) -#define UFS_PHY_RMMI_ATTRRDVAL_L0_STATUS PHY_OFF(0x16C) -#define UFS_PHY_RMMI_ATTRRDVAL_L1_STATUS PHY_OFF(0x170) -#define UFS_PHY_PCS_READY_STATUS PHY_OFF(0x174) - -#define UFS_PHY_TX_LANE_ENABLE_MASK 0x3 - -/* - * This structure represents the 20nm specific phy. - * common_cfg MUST remain the first field in this structure - * in case extra fields are added. This way, when calling - * get_ufs_qcom_phy() of generic phy, we can extract the - * common phy structure (struct ufs_qcom_phy) out of it - * regardless of the relevant specific phy. - */ -struct ufs_qcom_phy_qmp_20nm { - struct ufs_qcom_phy common_cfg; -}; - -static struct ufs_qcom_phy_calibration phy_cal_table_rate_A_1_2_0[] = { - UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_POWER_DOWN_CONTROL, 0x01), - UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_RX_SIGDET_CTRL3, 0x0D), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_VCOTAIL_EN, 0xe1), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CRCTRL, 0xcc), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_SYSCLK_EN_SEL_TXBAND, 0x08), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CLKEPDIV, 0x03), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_RXTXEPCLK_EN, 0x10), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DEC_START1, 0x82), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DEC_START2, 0x03), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START1, 0x80), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START2, 0x80), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START3, 0x40), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP1, 0xff), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP2, 0x19), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP3, 0x00), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP_EN, 0x03), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_RESETSM_CNTRL, 0x90), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_RESETSM_CNTRL2, 0x03), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL1(0), 0xf2), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL_HALF(0), 0x0c), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL_QUARTER(0), 0x12), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL1(1), 0xf2), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL_HALF(1), 0x0c), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL_QUARTER(1), 0x12), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_LSB(0), 0xff), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_MSB(0), 0xff), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_LSB(0), 0xff), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_MSB(0), 0x00), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_LSB(1), 0xff), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_MSB(1), 0xff), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_LSB(1), 0xff), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_MSB(1), 0x00), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CP_SETI, 0x3f), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_IP_SETP, 0x1b), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CP_SETP, 0x0f), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_IP_SETI, 0x01), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_EMP_POST1_LVL(0), 0x2F), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_DRV_LVL(0), 0x20), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_EMP_POST1_LVL(1), 0x2F), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_DRV_LVL(1), 0x20), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_LANE_MODE(0), 0x68), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_LANE_MODE(1), 0x68), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2(1), 0xdc), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2(0), 0xdc), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x3), -}; - -static struct ufs_qcom_phy_calibration phy_cal_table_rate_A_1_3_0[] = { - UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_POWER_DOWN_CONTROL, 0x01), - UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_RX_SIGDET_CTRL3, 0x0D), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_VCOTAIL_EN, 0xe1), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CRCTRL, 0xcc), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_SYSCLK_EN_SEL_TXBAND, 0x08), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CLKEPDIV, 0x03), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_RXTXEPCLK_EN, 0x10), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DEC_START1, 0x82), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DEC_START2, 0x03), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START1, 0x80), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START2, 0x80), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START3, 0x40), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP1, 0xff), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP2, 0x19), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP3, 0x00), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP_EN, 0x03), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_RESETSM_CNTRL, 0x90), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_RESETSM_CNTRL2, 0x03), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL1(0), 0xf2), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL_HALF(0), 0x0c), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL_QUARTER(0), 0x12), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL1(1), 0xf2), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL_HALF(1), 0x0c), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_CDR_CONTROL_QUARTER(1), 0x12), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_LSB(0), 0xff), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_MSB(0), 0xff), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_LSB(0), 0xff), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_MSB(0), 0x00), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_LSB(1), 0xff), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_MSB(1), 0xff), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_LSB(1), 0xff), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_MSB(1), 0x00), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CP_SETI, 0x2b), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_IP_SETP, 0x38), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CP_SETP, 0x3c), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_RES_CODE_UP_OFFSET, 0x02), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_RES_CODE_DN_OFFSET, 0x02), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_IP_SETI, 0x01), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CNTRL, 0x40), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_LANE_MODE(0), 0x68), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_LANE_MODE(1), 0x68), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2(1), 0xdc), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2(0), 0xdc), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x3), -}; - -static struct ufs_qcom_phy_calibration phy_cal_table_rate_B[] = { - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DEC_START1, 0x98), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP1, 0x65), - UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLLLOCK_CMP2, 0x1e), -}; - -#endif diff --git a/drivers/phy/phy-qcom-ufs.c~HEAD b/drivers/phy/phy-qcom-ufs.c~HEAD deleted file mode 100644 index 107cb57c3513..000000000000 --- a/drivers/phy/phy-qcom-ufs.c~HEAD +++ /dev/null @@ -1,749 +0,0 @@ -/* - * Copyright (c) 2013-2015, Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include "phy-qcom-ufs-i.h" - -#define MAX_PROP_NAME 32 -#define VDDA_PHY_MIN_UV 1000000 -#define VDDA_PHY_MAX_UV 1000000 -#define VDDA_PLL_MIN_UV 1800000 -#define VDDA_PLL_MAX_UV 1800000 -#define VDDP_REF_CLK_MIN_UV 1200000 -#define VDDP_REF_CLK_MAX_UV 1200000 - -static int __ufs_qcom_phy_init_vreg(struct phy *, struct ufs_qcom_phy_vreg *, - const char *, bool); -static int ufs_qcom_phy_init_vreg(struct phy *, struct ufs_qcom_phy_vreg *, - const char *); -static int ufs_qcom_phy_base_init(struct platform_device *pdev, - struct ufs_qcom_phy *phy_common); - -int ufs_qcom_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy, - struct ufs_qcom_phy_calibration *tbl_A, - int tbl_size_A, - struct ufs_qcom_phy_calibration *tbl_B, - int tbl_size_B, bool is_rate_B) -{ - int i; - int ret = 0; - - if (!tbl_A) { - dev_err(ufs_qcom_phy->dev, "%s: tbl_A is NULL", __func__); - ret = EINVAL; - goto out; - } - - for (i = 0; i < tbl_size_A; i++) - writel_relaxed(tbl_A[i].cfg_value, - ufs_qcom_phy->mmio + tbl_A[i].reg_offset); - - /* - * In case we would like to work in rate B, we need - * to override a registers that were configured in rate A table - * with registers of rate B table. - * table. - */ - if (is_rate_B) { - if (!tbl_B) { - dev_err(ufs_qcom_phy->dev, "%s: tbl_B is NULL", - __func__); - ret = EINVAL; - goto out; - } - - for (i = 0; i < tbl_size_B; i++) - writel_relaxed(tbl_B[i].cfg_value, - ufs_qcom_phy->mmio + tbl_B[i].reg_offset); - } - - /* flush buffered writes */ - mb(); - -out: - return ret; -} -EXPORT_SYMBOL_GPL(ufs_qcom_phy_calibrate); - -struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev, - struct ufs_qcom_phy *common_cfg, - const 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_load(reg, uA_load); - if (ret >= 0) { - /* - * regulator_set_load() 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; -} -EXPORT_SYMBOL_GPL(ufs_qcom_phy_enable_ref_clk); - -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; - } -} -EXPORT_SYMBOL_GPL(ufs_qcom_phy_disable_ref_clk); - -#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); -} -EXPORT_SYMBOL_GPL(ufs_qcom_phy_enable_dev_ref_clk); - -void ufs_qcom_phy_disable_dev_ref_clk(struct phy *generic_phy) -{ - ufs_qcom_phy_dev_ref_clk_ctrl(generic_phy, false); -} -EXPORT_SYMBOL_GPL(ufs_qcom_phy_disable_dev_ref_clk); - -/* 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; -} -EXPORT_SYMBOL_GPL(ufs_qcom_phy_enable_iface_clk); - -/* 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; - } -} -EXPORT_SYMBOL_GPL(ufs_qcom_phy_disable_iface_clk); - -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; -} -EXPORT_SYMBOL_GPL(ufs_qcom_phy_start_serdes); - -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; -} -EXPORT_SYMBOL_GPL(ufs_qcom_phy_set_tx_lane_enable); - -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; -} -EXPORT_SYMBOL_GPL(ufs_qcom_phy_save_controller_version); - -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; -} -EXPORT_SYMBOL_GPL(ufs_qcom_phy_calibrate_phy); - -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); -} -EXPORT_SYMBOL_GPL(ufs_qcom_phy_is_pcs_ready); - -int ufs_qcom_phy_power_on(struct phy *generic_phy) -{ - struct ufs_qcom_phy *phy_common = get_ufs_qcom_phy(generic_phy); - struct device *dev = phy_common->dev; - int err; - - err = ufs_qcom_phy_enable_vreg(generic_phy, &phy_common->vdda_phy); - if (err) { - dev_err(dev, "%s enable vdda_phy failed, err=%d\n", - __func__, err); - goto out; - } - - phy_common->phy_spec_ops->power_control(phy_common, true); - - /* vdda_pll also enables ref clock LDOs so enable it first */ - err = ufs_qcom_phy_enable_vreg(generic_phy, &phy_common->vdda_pll); - if (err) { - dev_err(dev, "%s enable vdda_pll failed, err=%d\n", - __func__, err); - goto out_disable_phy; - } - - err = ufs_qcom_phy_enable_ref_clk(generic_phy); - if (err) { - dev_err(dev, "%s enable phy ref clock failed, err=%d\n", - __func__, err); - goto out_disable_pll; - } - - /* enable device PHY ref_clk pad rail */ - if (phy_common->vddp_ref_clk.reg) { - err = ufs_qcom_phy_enable_vreg(generic_phy, - &phy_common->vddp_ref_clk); - if (err) { - dev_err(dev, "%s enable vddp_ref_clk failed, err=%d\n", - __func__, err); - goto out_disable_ref_clk; - } - } - - phy_common->is_powered_on = true; - goto out; - -out_disable_ref_clk: - ufs_qcom_phy_disable_ref_clk(generic_phy); -out_disable_pll: - ufs_qcom_phy_disable_vreg(generic_phy, &phy_common->vdda_pll); -out_disable_phy: - ufs_qcom_phy_disable_vreg(generic_phy, &phy_common->vdda_phy); -out: - return err; -} -EXPORT_SYMBOL_GPL(ufs_qcom_phy_power_on); - -int ufs_qcom_phy_power_off(struct phy *generic_phy) -{ - struct ufs_qcom_phy *phy_common = get_ufs_qcom_phy(generic_phy); - - phy_common->phy_spec_ops->power_control(phy_common, false); - - if (phy_common->vddp_ref_clk.reg) - ufs_qcom_phy_disable_vreg(generic_phy, - &phy_common->vddp_ref_clk); - ufs_qcom_phy_disable_ref_clk(generic_phy); - - ufs_qcom_phy_disable_vreg(generic_phy, &phy_common->vdda_pll); - ufs_qcom_phy_disable_vreg(generic_phy, &phy_common->vdda_phy); - phy_common->is_powered_on = false; - - return 0; -} -EXPORT_SYMBOL_GPL(ufs_qcom_phy_power_off); diff --git a/drivers/scsi/ufs/ufs-qcom.c~HEAD b/drivers/scsi/ufs/ufs-qcom.c~HEAD deleted file mode 100644 index 4f38d008bfb4..000000000000 --- a/drivers/scsi/ufs/ufs-qcom.c~HEAD +++ /dev/null @@ -1,1576 +0,0 @@ -/* - * Copyright (c) 2013-2015, Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include -#include -#include -#include - -#include -#include "ufshcd.h" -#include "ufshcd-pltfrm.h" -#include "unipro.h" -#include "ufs-qcom.h" -#include "ufshci.h" -#define UFS_QCOM_DEFAULT_DBG_PRINT_EN \ - (UFS_QCOM_DBG_PRINT_REGS_EN | UFS_QCOM_DBG_PRINT_TEST_BUS_EN) - -enum { - TSTBUS_UAWM, - TSTBUS_UARM, - TSTBUS_TXUC, - TSTBUS_RXUC, - TSTBUS_DFC, - TSTBUS_TRLUT, - TSTBUS_TMRLUT, - TSTBUS_OCSC, - TSTBUS_UTP_HCI, - TSTBUS_COMBINED, - TSTBUS_WRAPPER, - TSTBUS_UNIPRO, - TSTBUS_MAX, -}; - -static struct ufs_qcom_host *ufs_qcom_hosts[MAX_UFS_QCOM_HOSTS]; - -static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote); -static void ufs_qcom_get_default_testbus_cfg(struct ufs_qcom_host *host); -static int ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(struct ufs_hba *hba, - u32 clk_cycles); - -static void ufs_qcom_dump_regs(struct ufs_hba *hba, int offset, int len, - char *prefix) -{ - print_hex_dump(KERN_ERR, prefix, - len > 4 ? DUMP_PREFIX_OFFSET : DUMP_PREFIX_NONE, - 16, 4, (void __force *)hba->mmio_base + offset, - len * 4, false); -} - -static int ufs_qcom_get_connected_tx_lanes(struct ufs_hba *hba, u32 *tx_lanes) -{ - int err = 0; - - err = ufshcd_dme_get(hba, - UIC_ARG_MIB(PA_CONNECTEDTXDATALANES), tx_lanes); - if (err) - dev_err(hba->dev, "%s: couldn't read PA_CONNECTEDTXDATALANES %d\n", - __func__, err); - - return err; -} - -static int ufs_qcom_host_clk_get(struct device *dev, - const char *name, struct clk **clk_out) -{ - struct clk *clk; - int err = 0; - - clk = devm_clk_get(dev, name); - if (IS_ERR(clk)) { - err = PTR_ERR(clk); - dev_err(dev, "%s: failed to get %s err %d", - __func__, name, err); - } else { - *clk_out = clk; - } - - return err; -} - -static int ufs_qcom_host_clk_enable(struct device *dev, - const char *name, struct clk *clk) -{ - int err = 0; - - err = clk_prepare_enable(clk); - if (err) - dev_err(dev, "%s: %s enable failed %d\n", __func__, name, err); - - return err; -} - -static void ufs_qcom_disable_lane_clks(struct ufs_qcom_host *host) -{ - if (!host->is_lane_clks_enabled) - return; - - clk_disable_unprepare(host->tx_l1_sync_clk); - clk_disable_unprepare(host->tx_l0_sync_clk); - clk_disable_unprepare(host->rx_l1_sync_clk); - clk_disable_unprepare(host->rx_l0_sync_clk); - - host->is_lane_clks_enabled = false; -} - -static int ufs_qcom_enable_lane_clks(struct ufs_qcom_host *host) -{ - int err = 0; - struct device *dev = host->hba->dev; - - if (host->is_lane_clks_enabled) - return 0; - - err = ufs_qcom_host_clk_enable(dev, "rx_lane0_sync_clk", - host->rx_l0_sync_clk); - if (err) - goto out; - - err = ufs_qcom_host_clk_enable(dev, "tx_lane0_sync_clk", - host->tx_l0_sync_clk); - if (err) - goto disable_rx_l0; - - err = ufs_qcom_host_clk_enable(dev, "rx_lane1_sync_clk", - host->rx_l1_sync_clk); - if (err) - goto disable_tx_l0; - - err = ufs_qcom_host_clk_enable(dev, "tx_lane1_sync_clk", - host->tx_l1_sync_clk); - if (err) - goto disable_rx_l1; - - host->is_lane_clks_enabled = true; - goto out; - -disable_rx_l1: - clk_disable_unprepare(host->rx_l1_sync_clk); -disable_tx_l0: - clk_disable_unprepare(host->tx_l0_sync_clk); -disable_rx_l0: - clk_disable_unprepare(host->rx_l0_sync_clk); -out: - return err; -} - -static int ufs_qcom_init_lane_clks(struct ufs_qcom_host *host) -{ - int err = 0; - struct device *dev = host->hba->dev; - - err = ufs_qcom_host_clk_get(dev, - "rx_lane0_sync_clk", &host->rx_l0_sync_clk); - if (err) - goto out; - - err = ufs_qcom_host_clk_get(dev, - "tx_lane0_sync_clk", &host->tx_l0_sync_clk); - if (err) - goto out; - - err = ufs_qcom_host_clk_get(dev, "rx_lane1_sync_clk", - &host->rx_l1_sync_clk); - if (err) - goto out; - - err = ufs_qcom_host_clk_get(dev, "tx_lane1_sync_clk", - &host->tx_l1_sync_clk); - -out: - return err; -} - -static int ufs_qcom_link_startup_post_change(struct ufs_hba *hba) -{ - struct ufs_qcom_host *host = ufshcd_get_variant(hba); - struct phy *phy = host->generic_phy; - u32 tx_lanes; - int err = 0; - - err = ufs_qcom_get_connected_tx_lanes(hba, &tx_lanes); - if (err) - goto out; - - err = ufs_qcom_phy_set_tx_lane_enable(phy, tx_lanes); - if (err) - dev_err(hba->dev, "%s: ufs_qcom_phy_set_tx_lane_enable failed\n", - __func__); - -out: - return err; -} - -static int ufs_qcom_check_hibern8(struct ufs_hba *hba) -{ - int err; - u32 tx_fsm_val = 0; - unsigned long timeout = jiffies + msecs_to_jiffies(HBRN8_POLL_TOUT_MS); - - do { - err = ufshcd_dme_get(hba, - UIC_ARG_MIB_SEL(MPHY_TX_FSM_STATE, - UIC_ARG_MPHY_TX_GEN_SEL_INDEX(0)), - &tx_fsm_val); - if (err || tx_fsm_val == TX_FSM_HIBERN8) - break; - - /* sleep for max. 200us */ - usleep_range(100, 200); - } while (time_before(jiffies, timeout)); - - /* - * we might have scheduled out for long during polling so - * check the state again. - */ - if (time_after(jiffies, timeout)) - err = ufshcd_dme_get(hba, - UIC_ARG_MIB_SEL(MPHY_TX_FSM_STATE, - UIC_ARG_MPHY_TX_GEN_SEL_INDEX(0)), - &tx_fsm_val); - - if (err) { - dev_err(hba->dev, "%s: unable to get TX_FSM_STATE, err %d\n", - __func__, err); - } else if (tx_fsm_val != TX_FSM_HIBERN8) { - err = tx_fsm_val; - dev_err(hba->dev, "%s: invalid TX_FSM_STATE = %d\n", - __func__, err); - } - - return err; -} - -static void ufs_qcom_select_unipro_mode(struct ufs_qcom_host *host) -{ - ufshcd_rmwl(host->hba, QUNIPRO_SEL, - ufs_qcom_cap_qunipro(host) ? QUNIPRO_SEL : 0, - REG_UFS_CFG1); - /* make sure above configuration is applied before we return */ - mb(); -} - -static int ufs_qcom_power_up_sequence(struct ufs_hba *hba) -{ - struct ufs_qcom_host *host = ufshcd_get_variant(hba); - struct phy *phy = host->generic_phy; - int ret = 0; - bool is_rate_B = (UFS_QCOM_LIMIT_HS_RATE == PA_HS_MODE_B) - ? true : false; - - /* Assert PHY reset and apply PHY calibration values */ - ufs_qcom_assert_reset(hba); - /* provide 1ms delay to let the reset pulse propagate */ - usleep_range(1000, 1100); - - ret = ufs_qcom_phy_calibrate_phy(phy, is_rate_B); - - if (ret) { - dev_err(hba->dev, - "%s: ufs_qcom_phy_calibrate_phy()failed, ret = %d\n", - __func__, ret); - goto out; - } - - /* De-assert PHY reset and start serdes */ - ufs_qcom_deassert_reset(hba); - - /* - * after reset deassertion, phy will need all ref clocks, - * voltage, current to settle down before starting serdes. - */ - usleep_range(1000, 1100); - ret = ufs_qcom_phy_start_serdes(phy); - if (ret) { - dev_err(hba->dev, "%s: ufs_qcom_phy_start_serdes() failed, ret = %d\n", - __func__, ret); - goto out; - } - - ret = ufs_qcom_phy_is_pcs_ready(phy); - if (ret) - dev_err(hba->dev, - "%s: is_physical_coding_sublayer_ready() failed, ret = %d\n", - __func__, ret); - - ufs_qcom_select_unipro_mode(host); - -out: - return ret; -} - -/* - * The UTP controller has a number of internal clock gating cells (CGCs). - * Internal hardware sub-modules within the UTP controller control the CGCs. - * Hardware CGCs disable the clock to inactivate UTP sub-modules not involved - * in a specific operation, UTP controller CGCs are by default disabled and - * this function enables them (after every UFS link startup) to save some power - * leakage. - */ -static void ufs_qcom_enable_hw_clk_gating(struct ufs_hba *hba) -{ - ufshcd_writel(hba, - ufshcd_readl(hba, REG_UFS_CFG2) | REG_UFS_CFG2_CGC_EN_ALL, - REG_UFS_CFG2); - - /* Ensure that HW clock gating is enabled before next operations */ - mb(); -} - -static int ufs_qcom_hce_enable_notify(struct ufs_hba *hba, - enum ufs_notify_change_status status) -{ - struct ufs_qcom_host *host = ufshcd_get_variant(hba); - int err = 0; - - switch (status) { - case PRE_CHANGE: - ufs_qcom_power_up_sequence(hba); - /* - * The PHY PLL output is the source of tx/rx lane symbol - * clocks, hence, enable the lane clocks only after PHY - * is initialized. - */ - err = ufs_qcom_enable_lane_clks(host); - break; - case POST_CHANGE: - /* check if UFS PHY moved from DISABLED to HIBERN8 */ - err = ufs_qcom_check_hibern8(hba); - ufs_qcom_enable_hw_clk_gating(hba); - - break; - default: - dev_err(hba->dev, "%s: invalid status %d\n", __func__, status); - err = -EINVAL; - break; - } - return err; -} - -/** - * Returns zero for success and non-zero in case of a failure - */ -static int ufs_qcom_cfg_timers(struct ufs_hba *hba, u32 gear, - u32 hs, u32 rate, bool update_link_startup_timer) -{ - int ret = 0; - struct ufs_qcom_host *host = ufshcd_get_variant(hba); - struct ufs_clk_info *clki; - u32 core_clk_period_in_ns; - u32 tx_clk_cycles_per_us = 0; - unsigned long core_clk_rate = 0; - u32 core_clk_cycles_per_us = 0; - - static u32 pwm_fr_table[][2] = { - {UFS_PWM_G1, 0x1}, - {UFS_PWM_G2, 0x1}, - {UFS_PWM_G3, 0x1}, - {UFS_PWM_G4, 0x1}, - }; - - static u32 hs_fr_table_rA[][2] = { - {UFS_HS_G1, 0x1F}, - {UFS_HS_G2, 0x3e}, - {UFS_HS_G3, 0x7D}, - }; - - static u32 hs_fr_table_rB[][2] = { - {UFS_HS_G1, 0x24}, - {UFS_HS_G2, 0x49}, - {UFS_HS_G3, 0x92}, - }; - - /* - * The Qunipro controller does not use following registers: - * SYS1CLK_1US_REG, TX_SYMBOL_CLK_1US_REG, CLK_NS_REG & - * UFS_REG_PA_LINK_STARTUP_TIMER - * But UTP controller uses SYS1CLK_1US_REG register for Interrupt - * Aggregation logic. - */ - if (ufs_qcom_cap_qunipro(host) && !ufshcd_is_intr_aggr_allowed(hba)) - goto out; - - if (gear == 0) { - dev_err(hba->dev, "%s: invalid gear = %d\n", __func__, gear); - goto out_error; - } - - list_for_each_entry(clki, &hba->clk_list_head, list) { - if (!strcmp(clki->name, "core_clk")) - core_clk_rate = clk_get_rate(clki->clk); - } - - /* If frequency is smaller than 1MHz, set to 1MHz */ - if (core_clk_rate < DEFAULT_CLK_RATE_HZ) - core_clk_rate = DEFAULT_CLK_RATE_HZ; - - core_clk_cycles_per_us = core_clk_rate / USEC_PER_SEC; - if (ufshcd_readl(hba, REG_UFS_SYS1CLK_1US) != core_clk_cycles_per_us) { - ufshcd_writel(hba, core_clk_cycles_per_us, REG_UFS_SYS1CLK_1US); - /* - * make sure above write gets applied before we return from - * this function. - */ - mb(); - } - - if (ufs_qcom_cap_qunipro(host)) - goto out; - - core_clk_period_in_ns = NSEC_PER_SEC / core_clk_rate; - core_clk_period_in_ns <<= OFFSET_CLK_NS_REG; - core_clk_period_in_ns &= MASK_CLK_NS_REG; - - switch (hs) { - case FASTAUTO_MODE: - case FAST_MODE: - if (rate == PA_HS_MODE_A) { - if (gear > ARRAY_SIZE(hs_fr_table_rA)) { - dev_err(hba->dev, - "%s: index %d exceeds table size %zu\n", - __func__, gear, - ARRAY_SIZE(hs_fr_table_rA)); - goto out_error; - } - tx_clk_cycles_per_us = hs_fr_table_rA[gear-1][1]; - } else if (rate == PA_HS_MODE_B) { - if (gear > ARRAY_SIZE(hs_fr_table_rB)) { - dev_err(hba->dev, - "%s: index %d exceeds table size %zu\n", - __func__, gear, - ARRAY_SIZE(hs_fr_table_rB)); - goto out_error; - } - tx_clk_cycles_per_us = hs_fr_table_rB[gear-1][1]; - } else { - dev_err(hba->dev, "%s: invalid rate = %d\n", - __func__, rate); - goto out_error; - } - break; - case SLOWAUTO_MODE: - case SLOW_MODE: - if (gear > ARRAY_SIZE(pwm_fr_table)) { - dev_err(hba->dev, - "%s: index %d exceeds table size %zu\n", - __func__, gear, - ARRAY_SIZE(pwm_fr_table)); - goto out_error; - } - tx_clk_cycles_per_us = pwm_fr_table[gear-1][1]; - break; - case UNCHANGED: - default: - dev_err(hba->dev, "%s: invalid mode = %d\n", __func__, hs); - goto out_error; - } - - if (ufshcd_readl(hba, REG_UFS_TX_SYMBOL_CLK_NS_US) != - (core_clk_period_in_ns | tx_clk_cycles_per_us)) { - /* this register 2 fields shall be written at once */ - ufshcd_writel(hba, core_clk_period_in_ns | tx_clk_cycles_per_us, - REG_UFS_TX_SYMBOL_CLK_NS_US); - /* - * make sure above write gets applied before we return from - * this function. - */ - mb(); - } - - if (update_link_startup_timer) { - ufshcd_writel(hba, ((core_clk_rate / MSEC_PER_SEC) * 100), - REG_UFS_PA_LINK_STARTUP_TIMER); - /* - * make sure that this configuration is applied before - * we return - */ - mb(); - } - goto out; - -out_error: - ret = -EINVAL; -out: - return ret; -} - -static int ufs_qcom_link_startup_notify(struct ufs_hba *hba, - enum ufs_notify_change_status status) -{ - int err = 0; - struct ufs_qcom_host *host = ufshcd_get_variant(hba); - - switch (status) { - case PRE_CHANGE: - if (ufs_qcom_cfg_timers(hba, UFS_PWM_G1, SLOWAUTO_MODE, - 0, true)) { - dev_err(hba->dev, "%s: ufs_qcom_cfg_timers() failed\n", - __func__); - err = -EINVAL; - goto out; - } - - if (ufs_qcom_cap_qunipro(host)) - /* - * set unipro core clock cycles to 150 & clear clock - * divider - */ - err = ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(hba, - 150); - - break; - case POST_CHANGE: - ufs_qcom_link_startup_post_change(hba); - break; - default: - break; - } - -out: - return err; -} - -static int ufs_qcom_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) -{ - struct ufs_qcom_host *host = ufshcd_get_variant(hba); - struct phy *phy = host->generic_phy; - int ret = 0; - - if (ufs_qcom_is_link_off(hba)) { - /* - * Disable the tx/rx lane symbol clocks before PHY is - * powered down as the PLL source should be disabled - * after downstream clocks are disabled. - */ - ufs_qcom_disable_lane_clks(host); - phy_power_off(phy); - - /* Assert PHY soft reset */ - ufs_qcom_assert_reset(hba); - goto out; - } - - /* - * If UniPro link is not active, PHY ref_clk, main PHY analog power - * rail and low noise analog power rail for PLL can be switched off. - */ - if (!ufs_qcom_is_link_active(hba)) { - ufs_qcom_disable_lane_clks(host); - phy_power_off(phy); - } - -out: - return ret; -} - -static int ufs_qcom_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) -{ - struct ufs_qcom_host *host = ufshcd_get_variant(hba); - struct phy *phy = host->generic_phy; - int err; - - err = phy_power_on(phy); - if (err) { - dev_err(hba->dev, "%s: failed enabling regs, err = %d\n", - __func__, err); - goto out; - } - - err = ufs_qcom_enable_lane_clks(host); - if (err) - goto out; - - hba->is_sys_suspended = false; - -out: - return err; -} - -struct ufs_qcom_dev_params { - u32 pwm_rx_gear; /* pwm rx gear to work in */ - u32 pwm_tx_gear; /* pwm tx gear to work in */ - u32 hs_rx_gear; /* hs rx gear to work in */ - u32 hs_tx_gear; /* hs tx gear to work in */ - u32 rx_lanes; /* number of rx lanes */ - u32 tx_lanes; /* number of tx lanes */ - u32 rx_pwr_pwm; /* rx pwm working pwr */ - u32 tx_pwr_pwm; /* tx pwm working pwr */ - u32 rx_pwr_hs; /* rx hs working pwr */ - u32 tx_pwr_hs; /* tx hs working pwr */ - u32 hs_rate; /* rate A/B to work in HS */ - u32 desired_working_mode; -}; - -static int ufs_qcom_get_pwr_dev_param(struct ufs_qcom_dev_params *qcom_param, - struct ufs_pa_layer_attr *dev_max, - struct ufs_pa_layer_attr *agreed_pwr) -{ - int min_qcom_gear; - int min_dev_gear; - bool is_dev_sup_hs = false; - bool is_qcom_max_hs = false; - - if (dev_max->pwr_rx == FAST_MODE) - is_dev_sup_hs = true; - - if (qcom_param->desired_working_mode == FAST) { - is_qcom_max_hs = true; - min_qcom_gear = min_t(u32, qcom_param->hs_rx_gear, - qcom_param->hs_tx_gear); - } else { - min_qcom_gear = min_t(u32, qcom_param->pwm_rx_gear, - qcom_param->pwm_tx_gear); - } - - /* - * device doesn't support HS but qcom_param->desired_working_mode is - * HS, thus device and qcom_param don't agree - */ - if (!is_dev_sup_hs && is_qcom_max_hs) { - pr_err("%s: failed to agree on power mode (device doesn't support HS but requested power is HS)\n", - __func__); - return -ENOTSUPP; - } else if (is_dev_sup_hs && is_qcom_max_hs) { - /* - * since device supports HS, it supports FAST_MODE. - * since qcom_param->desired_working_mode is also HS - * then final decision (FAST/FASTAUTO) is done according - * to qcom_params as it is the restricting factor - */ - agreed_pwr->pwr_rx = agreed_pwr->pwr_tx = - qcom_param->rx_pwr_hs; - } else { - /* - * here qcom_param->desired_working_mode is PWM. - * it doesn't matter whether device supports HS or PWM, - * in both cases qcom_param->desired_working_mode will - * determine the mode - */ - agreed_pwr->pwr_rx = agreed_pwr->pwr_tx = - qcom_param->rx_pwr_pwm; - } - - /* - * we would like tx to work in the minimum number of lanes - * between device capability and vendor preferences. - * the same decision will be made for rx - */ - agreed_pwr->lane_tx = min_t(u32, dev_max->lane_tx, - qcom_param->tx_lanes); - agreed_pwr->lane_rx = min_t(u32, dev_max->lane_rx, - qcom_param->rx_lanes); - - /* device maximum gear is the minimum between device rx and tx gears */ - min_dev_gear = min_t(u32, dev_max->gear_rx, dev_max->gear_tx); - - /* - * if both device capabilities and vendor pre-defined preferences are - * both HS or both PWM then set the minimum gear to be the chosen - * working gear. - * if one is PWM and one is HS then the one that is PWM get to decide - * what is the gear, as it is the one that also decided previously what - * pwr the device will be configured to. - */ - if ((is_dev_sup_hs && is_qcom_max_hs) || - (!is_dev_sup_hs && !is_qcom_max_hs)) - agreed_pwr->gear_rx = agreed_pwr->gear_tx = - min_t(u32, min_dev_gear, min_qcom_gear); - else if (!is_dev_sup_hs) - agreed_pwr->gear_rx = agreed_pwr->gear_tx = min_dev_gear; - else - agreed_pwr->gear_rx = agreed_pwr->gear_tx = min_qcom_gear; - - agreed_pwr->hs_rate = qcom_param->hs_rate; - return 0; -} - -#ifdef CONFIG_MSM_BUS_SCALING -static int ufs_qcom_get_bus_vote(struct ufs_qcom_host *host, - const char *speed_mode) -{ - struct device *dev = host->hba->dev; - struct device_node *np = dev->of_node; - int err; - const char *key = "qcom,bus-vector-names"; - - if (!speed_mode) { - err = -EINVAL; - goto out; - } - - if (host->bus_vote.is_max_bw_needed && !!strcmp(speed_mode, "MIN")) - err = of_property_match_string(np, key, "MAX"); - else - err = of_property_match_string(np, key, speed_mode); - -out: - if (err < 0) - dev_err(dev, "%s: Invalid %s mode %d\n", - __func__, speed_mode, err); - return err; -} - -static void ufs_qcom_get_speed_mode(struct ufs_pa_layer_attr *p, char *result) -{ - int gear = max_t(u32, p->gear_rx, p->gear_tx); - int lanes = max_t(u32, p->lane_rx, p->lane_tx); - int pwr; - - /* default to PWM Gear 1, Lane 1 if power mode is not initialized */ - if (!gear) - gear = 1; - - if (!lanes) - lanes = 1; - - if (!p->pwr_rx && !p->pwr_tx) { - pwr = SLOWAUTO_MODE; - snprintf(result, BUS_VECTOR_NAME_LEN, "MIN"); - } else if (p->pwr_rx == FAST_MODE || p->pwr_rx == FASTAUTO_MODE || - p->pwr_tx == FAST_MODE || p->pwr_tx == FASTAUTO_MODE) { - pwr = FAST_MODE; - snprintf(result, BUS_VECTOR_NAME_LEN, "%s_R%s_G%d_L%d", "HS", - p->hs_rate == PA_HS_MODE_B ? "B" : "A", gear, lanes); - } else { - pwr = SLOW_MODE; - snprintf(result, BUS_VECTOR_NAME_LEN, "%s_G%d_L%d", - "PWM", gear, lanes); - } -} - -static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote) -{ - int err = 0; - - if (vote != host->bus_vote.curr_vote) { - err = msm_bus_scale_client_update_request( - host->bus_vote.client_handle, vote); - if (err) { - dev_err(host->hba->dev, - "%s: msm_bus_scale_client_update_request() failed: bus_client_handle=0x%x, vote=%d, err=%d\n", - __func__, host->bus_vote.client_handle, - vote, err); - goto out; - } - - host->bus_vote.curr_vote = vote; - } -out: - return err; -} - -static int ufs_qcom_update_bus_bw_vote(struct ufs_qcom_host *host) -{ - int vote; - int err = 0; - char mode[BUS_VECTOR_NAME_LEN]; - - ufs_qcom_get_speed_mode(&host->dev_req_params, mode); - - vote = ufs_qcom_get_bus_vote(host, mode); - if (vote >= 0) - err = ufs_qcom_set_bus_vote(host, vote); - else - err = vote; - - if (err) - dev_err(host->hba->dev, "%s: failed %d\n", __func__, err); - else - host->bus_vote.saved_vote = vote; - return err; -} - -static ssize_t -show_ufs_to_mem_max_bus_bw(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct ufs_hba *hba = dev_get_drvdata(dev); - struct ufs_qcom_host *host = ufshcd_get_variant(hba); - - return snprintf(buf, PAGE_SIZE, "%u\n", - host->bus_vote.is_max_bw_needed); -} - -static ssize_t -store_ufs_to_mem_max_bus_bw(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct ufs_hba *hba = dev_get_drvdata(dev); - struct ufs_qcom_host *host = ufshcd_get_variant(hba); - uint32_t value; - - if (!kstrtou32(buf, 0, &value)) { - host->bus_vote.is_max_bw_needed = !!value; - ufs_qcom_update_bus_bw_vote(host); - } - - return count; -} - -static int ufs_qcom_bus_register(struct ufs_qcom_host *host) -{ - int err; - struct msm_bus_scale_pdata *bus_pdata; - struct device *dev = host->hba->dev; - struct platform_device *pdev = to_platform_device(dev); - struct device_node *np = dev->of_node; - - bus_pdata = msm_bus_cl_get_pdata(pdev); - if (!bus_pdata) { - dev_err(dev, "%s: failed to get bus vectors\n", __func__); - err = -ENODATA; - goto out; - } - - err = of_property_count_strings(np, "qcom,bus-vector-names"); - if (err < 0 || err != bus_pdata->num_usecases) { - dev_err(dev, "%s: qcom,bus-vector-names not specified correctly %d\n", - __func__, err); - goto out; - } - - host->bus_vote.client_handle = msm_bus_scale_register_client(bus_pdata); - if (!host->bus_vote.client_handle) { - dev_err(dev, "%s: msm_bus_scale_register_client failed\n", - __func__); - err = -EFAULT; - goto out; - } - - /* cache the vote index for minimum and maximum bandwidth */ - host->bus_vote.min_bw_vote = ufs_qcom_get_bus_vote(host, "MIN"); - host->bus_vote.max_bw_vote = ufs_qcom_get_bus_vote(host, "MAX"); - - host->bus_vote.max_bus_bw.show = show_ufs_to_mem_max_bus_bw; - host->bus_vote.max_bus_bw.store = store_ufs_to_mem_max_bus_bw; - sysfs_attr_init(&host->bus_vote.max_bus_bw.attr); - host->bus_vote.max_bus_bw.attr.name = "max_bus_bw"; - host->bus_vote.max_bus_bw.attr.mode = S_IRUGO | S_IWUSR; - err = device_create_file(dev, &host->bus_vote.max_bus_bw); -out: - return err; -} -#else /* CONFIG_MSM_BUS_SCALING */ -static int ufs_qcom_update_bus_bw_vote(struct ufs_qcom_host *host) -{ - return 0; -} - -static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote) -{ - return 0; -} - -static int ufs_qcom_bus_register(struct ufs_qcom_host *host) -{ - return 0; -} -#endif /* CONFIG_MSM_BUS_SCALING */ - -static void ufs_qcom_dev_ref_clk_ctrl(struct ufs_qcom_host *host, bool enable) -{ - if (host->dev_ref_clk_ctrl_mmio && - (enable ^ host->is_dev_ref_clk_enabled)) { - u32 temp = readl_relaxed(host->dev_ref_clk_ctrl_mmio); - - if (enable) - temp |= host->dev_ref_clk_en_mask; - else - temp &= ~host->dev_ref_clk_en_mask; - - /* - * If we are here to disable this clock it might be immediately - * after entering into hibern8 in which case we need to make - * sure that device ref_clk is active at least 1us after the - * hibern8 enter. - */ - if (!enable) - udelay(1); - - writel_relaxed(temp, host->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 at least 1us before the hibern8 - * exit command. - */ - if (enable) - udelay(1); - - host->is_dev_ref_clk_enabled = enable; - } -} - -static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba, - enum ufs_notify_change_status status, - struct ufs_pa_layer_attr *dev_max_params, - struct ufs_pa_layer_attr *dev_req_params) -{ - u32 val; - struct ufs_qcom_host *host = ufshcd_get_variant(hba); - struct phy *phy = host->generic_phy; - struct ufs_qcom_dev_params ufs_qcom_cap; - int ret = 0; - int res = 0; - - if (!dev_req_params) { - pr_err("%s: incoming dev_req_params is NULL\n", __func__); - ret = -EINVAL; - goto out; - } - - switch (status) { - case PRE_CHANGE: - ufs_qcom_cap.tx_lanes = UFS_QCOM_LIMIT_NUM_LANES_TX; - ufs_qcom_cap.rx_lanes = UFS_QCOM_LIMIT_NUM_LANES_RX; - ufs_qcom_cap.hs_rx_gear = UFS_QCOM_LIMIT_HSGEAR_RX; - ufs_qcom_cap.hs_tx_gear = UFS_QCOM_LIMIT_HSGEAR_TX; - ufs_qcom_cap.pwm_rx_gear = UFS_QCOM_LIMIT_PWMGEAR_RX; - ufs_qcom_cap.pwm_tx_gear = UFS_QCOM_LIMIT_PWMGEAR_TX; - ufs_qcom_cap.rx_pwr_pwm = UFS_QCOM_LIMIT_RX_PWR_PWM; - ufs_qcom_cap.tx_pwr_pwm = UFS_QCOM_LIMIT_TX_PWR_PWM; - ufs_qcom_cap.rx_pwr_hs = UFS_QCOM_LIMIT_RX_PWR_HS; - ufs_qcom_cap.tx_pwr_hs = UFS_QCOM_LIMIT_TX_PWR_HS; - ufs_qcom_cap.hs_rate = UFS_QCOM_LIMIT_HS_RATE; - ufs_qcom_cap.desired_working_mode = - UFS_QCOM_LIMIT_DESIRED_MODE; - - if (host->hw_ver.major == 0x1) { - /* - * HS-G3 operations may not reliably work on legacy QCOM - * UFS host controller hardware even though capability - * exchange during link startup phase may end up - * negotiating maximum supported gear as G3. - * Hence downgrade the maximum supported gear to HS-G2. - */ - if (ufs_qcom_cap.hs_tx_gear > UFS_HS_G2) - ufs_qcom_cap.hs_tx_gear = UFS_HS_G2; - if (ufs_qcom_cap.hs_rx_gear > UFS_HS_G2) - ufs_qcom_cap.hs_rx_gear = UFS_HS_G2; - } - - ret = ufs_qcom_get_pwr_dev_param(&ufs_qcom_cap, - dev_max_params, - dev_req_params); - if (ret) { - pr_err("%s: failed to determine capabilities\n", - __func__); - goto out; - } - - break; - case POST_CHANGE: - if (ufs_qcom_cfg_timers(hba, dev_req_params->gear_rx, - dev_req_params->pwr_rx, - dev_req_params->hs_rate, false)) { - dev_err(hba->dev, "%s: ufs_qcom_cfg_timers() failed\n", - __func__); - /* - * we return error code at the end of the routine, - * but continue to configure UFS_PHY_TX_LANE_ENABLE - * and bus voting as usual - */ - ret = -EINVAL; - } - - val = ~(MAX_U32 << dev_req_params->lane_tx); - res = ufs_qcom_phy_set_tx_lane_enable(phy, val); - if (res) { - dev_err(hba->dev, "%s: ufs_qcom_phy_set_tx_lane_enable() failed res = %d\n", - __func__, res); - ret = res; - } - - /* cache the power mode parameters to use internally */ - memcpy(&host->dev_req_params, - dev_req_params, sizeof(*dev_req_params)); - ufs_qcom_update_bus_bw_vote(host); - break; - default: - ret = -EINVAL; - break; - } -out: - return ret; -} - -static u32 ufs_qcom_get_ufs_hci_version(struct ufs_hba *hba) -{ - struct ufs_qcom_host *host = ufshcd_get_variant(hba); - - if (host->hw_ver.major == 0x1) - return UFSHCI_VERSION_11; - else - return UFSHCI_VERSION_20; -} - -/** - * ufs_qcom_advertise_quirks - advertise the known QCOM UFS controller quirks - * @hba: host controller instance - * - * QCOM UFS host controller might have some non standard behaviours (quirks) - * than what is specified by UFSHCI specification. Advertise all such - * quirks to standard UFS host controller driver so standard takes them into - * account. - */ -static void ufs_qcom_advertise_quirks(struct ufs_hba *hba) -{ - struct ufs_qcom_host *host = ufshcd_get_variant(hba); - - if (host->hw_ver.major == 0x01) { - hba->quirks |= UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS - | UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP - | UFSHCD_QUIRK_DME_PEER_ACCESS_AUTO_MODE; - - if (host->hw_ver.minor == 0x0001 && host->hw_ver.step == 0x0001) - hba->quirks |= UFSHCD_QUIRK_BROKEN_INTR_AGGR; - - hba->quirks |= UFSHCD_QUIRK_BROKEN_LCC; - } - - if (host->hw_ver.major >= 0x2) { - hba->quirks |= UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION; - - if (!ufs_qcom_cap_qunipro(host)) - /* Legacy UniPro mode still need following quirks */ - hba->quirks |= (UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS - | UFSHCD_QUIRK_DME_PEER_ACCESS_AUTO_MODE - | UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP); - } -} - -static void ufs_qcom_set_caps(struct ufs_hba *hba) -{ - struct ufs_qcom_host *host = ufshcd_get_variant(hba); - - hba->caps |= UFSHCD_CAP_CLK_GATING | UFSHCD_CAP_HIBERN8_WITH_CLK_GATING; - hba->caps |= UFSHCD_CAP_CLK_SCALING; - hba->caps |= UFSHCD_CAP_AUTO_BKOPS_SUSPEND; - - if (host->hw_ver.major >= 0x2) { - host->caps = UFS_QCOM_CAP_QUNIPRO | - UFS_QCOM_CAP_RETAIN_SEC_CFG_AFTER_PWR_COLLAPSE; - } -} - -/** - * ufs_qcom_setup_clocks - enables/disable clocks - * @hba: host controller instance - * @on: If true, enable clocks else disable them. - * - * Returns 0 on success, non-zero on failure. - */ -static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on) -{ - struct ufs_qcom_host *host = ufshcd_get_variant(hba); - int err; - int vote = 0; - - /* - * In case ufs_qcom_init() is not yet done, simply ignore. - * This ufs_qcom_setup_clocks() shall be called from - * ufs_qcom_init() after init is done. - */ - if (!host) - return 0; - - if (on) { - err = ufs_qcom_phy_enable_iface_clk(host->generic_phy); - if (err) - goto out; - - err = ufs_qcom_phy_enable_ref_clk(host->generic_phy); - if (err) { - dev_err(hba->dev, "%s enable phy ref clock failed, err=%d\n", - __func__, err); - ufs_qcom_phy_disable_iface_clk(host->generic_phy); - goto out; - } - vote = host->bus_vote.saved_vote; - if (vote == host->bus_vote.min_bw_vote) - ufs_qcom_update_bus_bw_vote(host); - - } else { - - /* M-PHY RMMI interface clocks can be turned off */ - ufs_qcom_phy_disable_iface_clk(host->generic_phy); - if (!ufs_qcom_is_link_active(hba)) - /* disable device ref_clk */ - ufs_qcom_dev_ref_clk_ctrl(host, false); - - vote = host->bus_vote.min_bw_vote; - } - - err = ufs_qcom_set_bus_vote(host, vote); - if (err) - dev_err(hba->dev, "%s: set bus vote failed %d\n", - __func__, err); - -out: - return err; -} - -#define ANDROID_BOOT_DEV_MAX 30 -static char android_boot_dev[ANDROID_BOOT_DEV_MAX]; - -#ifndef MODULE -static int __init get_android_boot_dev(char *str) -{ - strlcpy(android_boot_dev, str, ANDROID_BOOT_DEV_MAX); - return 1; -} -__setup("androidboot.bootdevice=", get_android_boot_dev); -#endif - -/** - * ufs_qcom_init - bind phy with controller - * @hba: host controller instance - * - * Binds PHY with controller and powers up PHY enabling clocks - * and regulators. - * - * Returns -EPROBE_DEFER if binding fails, returns negative error - * on phy power up failure and returns zero on success. - */ -static int ufs_qcom_init(struct ufs_hba *hba) -{ - int err; - struct device *dev = hba->dev; - struct platform_device *pdev = to_platform_device(dev); - struct ufs_qcom_host *host; - struct resource *res; - - if (strlen(android_boot_dev) && strcmp(android_boot_dev, dev_name(dev))) - return -ENODEV; - - host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL); - if (!host) { - err = -ENOMEM; - dev_err(dev, "%s: no memory for qcom ufs host\n", __func__); - goto out; - } - - /* Make a two way bind between the qcom host and the hba */ - host->hba = hba; - ufshcd_set_variant(hba, host); - - /* - * voting/devoting device ref_clk source is time consuming hence - * skip devoting it during aggressive clock gating. This clock - * will still be gated off during runtime suspend. - */ - host->generic_phy = devm_phy_get(dev, "ufsphy"); - - if (IS_ERR(host->generic_phy)) { - err = PTR_ERR(host->generic_phy); - dev_err(dev, "%s: PHY get failed %d\n", __func__, err); - goto out; - } - - err = ufs_qcom_bus_register(host); - if (err) - goto out_host_free; - - ufs_qcom_get_controller_revision(hba, &host->hw_ver.major, - &host->hw_ver.minor, &host->hw_ver.step); - - /* - * for newer controllers, device reference clock control bit has - * moved inside UFS controller register address space itself. - */ - if (host->hw_ver.major >= 0x02) { - host->dev_ref_clk_ctrl_mmio = hba->mmio_base + REG_UFS_CFG1; - host->dev_ref_clk_en_mask = BIT(26); - } else { - /* "dev_ref_clk_ctrl_mem" is optional resource */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (res) { - host->dev_ref_clk_ctrl_mmio = - devm_ioremap_resource(dev, res); - if (IS_ERR(host->dev_ref_clk_ctrl_mmio)) { - dev_warn(dev, - "%s: could not map dev_ref_clk_ctrl_mmio, err %ld\n", - __func__, - PTR_ERR(host->dev_ref_clk_ctrl_mmio)); - host->dev_ref_clk_ctrl_mmio = NULL; - } - host->dev_ref_clk_en_mask = BIT(5); - } - } - - /* update phy revision information before calling phy_init() */ - ufs_qcom_phy_save_controller_version(host->generic_phy, - host->hw_ver.major, host->hw_ver.minor, host->hw_ver.step); - - phy_init(host->generic_phy); - err = phy_power_on(host->generic_phy); - if (err) - goto out_unregister_bus; - - err = ufs_qcom_init_lane_clks(host); - if (err) - goto out_disable_phy; - - ufs_qcom_set_caps(hba); - ufs_qcom_advertise_quirks(hba); - - ufs_qcom_setup_clocks(hba, true); - - if (hba->dev->id < MAX_UFS_QCOM_HOSTS) - ufs_qcom_hosts[hba->dev->id] = host; - - host->dbg_print_en |= UFS_QCOM_DEFAULT_DBG_PRINT_EN; - ufs_qcom_get_default_testbus_cfg(host); - err = ufs_qcom_testbus_config(host); - if (err) { - dev_warn(dev, "%s: failed to configure the testbus %d\n", - __func__, err); - err = 0; - } - - goto out; - -out_disable_phy: - phy_power_off(host->generic_phy); -out_unregister_bus: - phy_exit(host->generic_phy); -out_host_free: - devm_kfree(dev, host); - ufshcd_set_variant(hba, NULL); -out: - return err; -} - -static void ufs_qcom_exit(struct ufs_hba *hba) -{ - struct ufs_qcom_host *host = ufshcd_get_variant(hba); - - ufs_qcom_disable_lane_clks(host); - phy_power_off(host->generic_phy); -} - -static int ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(struct ufs_hba *hba, - u32 clk_cycles) -{ - int err; - u32 core_clk_ctrl_reg; - - if (clk_cycles > DME_VS_CORE_CLK_CTRL_MAX_CORE_CLK_1US_CYCLES_MASK) - return -EINVAL; - - err = ufshcd_dme_get(hba, - UIC_ARG_MIB(DME_VS_CORE_CLK_CTRL), - &core_clk_ctrl_reg); - if (err) - goto out; - - core_clk_ctrl_reg &= ~DME_VS_CORE_CLK_CTRL_MAX_CORE_CLK_1US_CYCLES_MASK; - core_clk_ctrl_reg |= clk_cycles; - - /* Clear CORE_CLK_DIV_EN */ - core_clk_ctrl_reg &= ~DME_VS_CORE_CLK_CTRL_CORE_CLK_DIV_EN_BIT; - - err = ufshcd_dme_set(hba, - UIC_ARG_MIB(DME_VS_CORE_CLK_CTRL), - core_clk_ctrl_reg); -out: - return err; -} - -static int ufs_qcom_clk_scale_up_pre_change(struct ufs_hba *hba) -{ - /* nothing to do as of now */ - return 0; -} - -static int ufs_qcom_clk_scale_up_post_change(struct ufs_hba *hba) -{ - struct ufs_qcom_host *host = ufshcd_get_variant(hba); - - if (!ufs_qcom_cap_qunipro(host)) - return 0; - - /* set unipro core clock cycles to 150 and clear clock divider */ - return ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(hba, 150); -} - -static int ufs_qcom_clk_scale_down_pre_change(struct ufs_hba *hba) -{ - struct ufs_qcom_host *host = ufshcd_get_variant(hba); - int err; - u32 core_clk_ctrl_reg; - - if (!ufs_qcom_cap_qunipro(host)) - return 0; - - err = ufshcd_dme_get(hba, - UIC_ARG_MIB(DME_VS_CORE_CLK_CTRL), - &core_clk_ctrl_reg); - - /* make sure CORE_CLK_DIV_EN is cleared */ - if (!err && - (core_clk_ctrl_reg & DME_VS_CORE_CLK_CTRL_CORE_CLK_DIV_EN_BIT)) { - core_clk_ctrl_reg &= ~DME_VS_CORE_CLK_CTRL_CORE_CLK_DIV_EN_BIT; - err = ufshcd_dme_set(hba, - UIC_ARG_MIB(DME_VS_CORE_CLK_CTRL), - core_clk_ctrl_reg); - } - - return err; -} - -static int ufs_qcom_clk_scale_down_post_change(struct ufs_hba *hba) -{ - struct ufs_qcom_host *host = ufshcd_get_variant(hba); - - if (!ufs_qcom_cap_qunipro(host)) - return 0; - - /* set unipro core clock cycles to 75 and clear clock divider */ - return ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(hba, 75); -} - -static int ufs_qcom_clk_scale_notify(struct ufs_hba *hba, - bool scale_up, enum ufs_notify_change_status status) -{ - struct ufs_qcom_host *host = ufshcd_get_variant(hba); - struct ufs_pa_layer_attr *dev_req_params = &host->dev_req_params; - int err = 0; - - if (status == PRE_CHANGE) { - if (scale_up) - err = ufs_qcom_clk_scale_up_pre_change(hba); - else - err = ufs_qcom_clk_scale_down_pre_change(hba); - } else { - if (scale_up) - err = ufs_qcom_clk_scale_up_post_change(hba); - else - err = ufs_qcom_clk_scale_down_post_change(hba); - - if (err || !dev_req_params) - goto out; - - ufs_qcom_cfg_timers(hba, - dev_req_params->gear_rx, - dev_req_params->pwr_rx, - dev_req_params->hs_rate, - false); - ufs_qcom_update_bus_bw_vote(host); - } - -out: - return err; -} - -static void ufs_qcom_get_default_testbus_cfg(struct ufs_qcom_host *host) -{ - /* provide a legal default configuration */ - host->testbus.select_major = TSTBUS_UAWM; - host->testbus.select_minor = 1; -} - -static bool ufs_qcom_testbus_cfg_is_ok(struct ufs_qcom_host *host) -{ - if (host->testbus.select_major >= TSTBUS_MAX) { - dev_err(host->hba->dev, - "%s: UFS_CFG1[TEST_BUS_SEL} may not equal 0x%05X\n", - __func__, host->testbus.select_major); - return false; - } - - /* - * Not performing check for each individual select_major - * mappings of select_minor, since there is no harm in - * configuring a non-existent select_minor - */ - if (host->testbus.select_minor > 0x1F) { - dev_err(host->hba->dev, - "%s: 0x%05X is not a legal testbus option\n", - __func__, host->testbus.select_minor); - return false; - } - - return true; -} - -int ufs_qcom_testbus_config(struct ufs_qcom_host *host) -{ - int reg; - int offset; - u32 mask = TEST_BUS_SUB_SEL_MASK; - - if (!host) - return -EINVAL; - - if (!ufs_qcom_testbus_cfg_is_ok(host)) - return -EPERM; - - switch (host->testbus.select_major) { - case TSTBUS_UAWM: - reg = UFS_TEST_BUS_CTRL_0; - offset = 24; - break; - case TSTBUS_UARM: - reg = UFS_TEST_BUS_CTRL_0; - offset = 16; - break; - case TSTBUS_TXUC: - reg = UFS_TEST_BUS_CTRL_0; - offset = 8; - break; - case TSTBUS_RXUC: - reg = UFS_TEST_BUS_CTRL_0; - offset = 0; - break; - case TSTBUS_DFC: - reg = UFS_TEST_BUS_CTRL_1; - offset = 24; - break; - case TSTBUS_TRLUT: - reg = UFS_TEST_BUS_CTRL_1; - offset = 16; - break; - case TSTBUS_TMRLUT: - reg = UFS_TEST_BUS_CTRL_1; - offset = 8; - break; - case TSTBUS_OCSC: - reg = UFS_TEST_BUS_CTRL_1; - offset = 0; - break; - case TSTBUS_WRAPPER: - reg = UFS_TEST_BUS_CTRL_2; - offset = 16; - break; - case TSTBUS_COMBINED: - reg = UFS_TEST_BUS_CTRL_2; - offset = 8; - break; - case TSTBUS_UTP_HCI: - reg = UFS_TEST_BUS_CTRL_2; - offset = 0; - break; - case TSTBUS_UNIPRO: - reg = UFS_UNIPRO_CFG; - offset = 1; - break; - /* - * No need for a default case, since - * ufs_qcom_testbus_cfg_is_ok() checks that the configuration - * is legal - */ - } - mask <<= offset; - - pm_runtime_get_sync(host->hba->dev); - ufshcd_hold(host->hba, false); - ufshcd_rmwl(host->hba, TEST_BUS_SEL, - (u32)host->testbus.select_major << 19, - REG_UFS_CFG1); - ufshcd_rmwl(host->hba, mask, - (u32)host->testbus.select_minor << offset, - reg); - ufshcd_release(host->hba); - pm_runtime_put_sync(host->hba->dev); - - return 0; -} - -static void ufs_qcom_testbus_read(struct ufs_hba *hba) -{ - ufs_qcom_dump_regs(hba, UFS_TEST_BUS, 1, "UFS_TEST_BUS "); -} - -static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba) -{ - ufs_qcom_dump_regs(hba, REG_UFS_SYS1CLK_1US, 16, - "HCI Vendor Specific Registers "); - - ufs_qcom_testbus_read(hba); -} -/** - * struct ufs_hba_qcom_vops - UFS QCOM specific variant operations - * - * The variant operations configure the necessary controller and PHY - * handshake during initialization. - */ -static struct ufs_hba_variant_ops ufs_hba_qcom_vops = { - .name = "qcom", - .init = ufs_qcom_init, - .exit = ufs_qcom_exit, - .get_ufs_hci_version = ufs_qcom_get_ufs_hci_version, - .clk_scale_notify = ufs_qcom_clk_scale_notify, - .setup_clocks = ufs_qcom_setup_clocks, - .hce_enable_notify = ufs_qcom_hce_enable_notify, - .link_startup_notify = ufs_qcom_link_startup_notify, - .pwr_change_notify = ufs_qcom_pwr_change_notify, - .suspend = ufs_qcom_suspend, - .resume = ufs_qcom_resume, - .dbg_register_dump = ufs_qcom_dump_dbg_regs, -}; - -/** - * ufs_qcom_probe - probe routine of the driver - * @pdev: pointer to Platform device handle - * - * Return zero for success and non-zero for failure - */ -static int ufs_qcom_probe(struct platform_device *pdev) -{ - int err; - struct device *dev = &pdev->dev; - - /* Perform generic probe */ - err = ufshcd_pltfrm_init(pdev, &ufs_hba_qcom_vops); - if (err) - dev_err(dev, "ufshcd_pltfrm_init() failed %d\n", err); - - return err; -} - -/** - * ufs_qcom_remove - set driver_data of the device to NULL - * @pdev: pointer to platform device handle - * - * Always return 0 - */ -static int ufs_qcom_remove(struct platform_device *pdev) -{ - struct ufs_hba *hba = platform_get_drvdata(pdev); - - pm_runtime_get_sync(&(pdev)->dev); - ufshcd_remove(hba); - return 0; -} - -static const struct of_device_id ufs_qcom_of_match[] = { - { .compatible = "qcom,ufshc"}, - {}, -}; - -static const struct dev_pm_ops ufs_qcom_pm_ops = { - .suspend = ufshcd_pltfrm_suspend, - .resume = ufshcd_pltfrm_resume, - .runtime_suspend = ufshcd_pltfrm_runtime_suspend, - .runtime_resume = ufshcd_pltfrm_runtime_resume, - .runtime_idle = ufshcd_pltfrm_runtime_idle, -}; - -static struct platform_driver ufs_qcom_pltform = { - .probe = ufs_qcom_probe, - .remove = ufs_qcom_remove, - .shutdown = ufshcd_pltfrm_shutdown, - .driver = { - .name = "ufshcd-qcom", - .pm = &ufs_qcom_pm_ops, - .of_match_table = of_match_ptr(ufs_qcom_of_match), - }, -}; -module_platform_driver(ufs_qcom_pltform); - -MODULE_LICENSE("GPL v2"); diff --git a/drivers/scsi/ufs/ufs-qcom.h~HEAD b/drivers/scsi/ufs/ufs-qcom.h~HEAD deleted file mode 100644 index 36249b35f858..000000000000 --- a/drivers/scsi/ufs/ufs-qcom.h~HEAD +++ /dev/null @@ -1,258 +0,0 @@ -/* Copyright (c) 2013-2015, The 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_H_ -#define UFS_QCOM_H_ - -#define MAX_UFS_QCOM_HOSTS 1 -#define MAX_U32 (~(u32)0) -#define MPHY_TX_FSM_STATE 0x41 -#define TX_FSM_HIBERN8 0x1 -#define HBRN8_POLL_TOUT_MS 100 -#define DEFAULT_CLK_RATE_HZ 1000000 -#define BUS_VECTOR_NAME_LEN 32 - -#define UFS_HW_VER_MAJOR_SHFT (28) -#define UFS_HW_VER_MAJOR_MASK (0x000F << UFS_HW_VER_MAJOR_SHFT) -#define UFS_HW_VER_MINOR_SHFT (16) -#define UFS_HW_VER_MINOR_MASK (0x0FFF << UFS_HW_VER_MINOR_SHFT) -#define UFS_HW_VER_STEP_SHFT (0) -#define UFS_HW_VER_STEP_MASK (0xFFFF << UFS_HW_VER_STEP_SHFT) - -/* vendor specific pre-defined parameters */ -#define SLOW 1 -#define FAST 2 - -#define UFS_QCOM_LIMIT_NUM_LANES_RX 2 -#define UFS_QCOM_LIMIT_NUM_LANES_TX 2 -#define UFS_QCOM_LIMIT_HSGEAR_RX UFS_HS_G3 -#define UFS_QCOM_LIMIT_HSGEAR_TX UFS_HS_G3 -#define UFS_QCOM_LIMIT_PWMGEAR_RX UFS_PWM_G4 -#define UFS_QCOM_LIMIT_PWMGEAR_TX UFS_PWM_G4 -#define UFS_QCOM_LIMIT_RX_PWR_PWM SLOW_MODE -#define UFS_QCOM_LIMIT_TX_PWR_PWM SLOW_MODE -#define UFS_QCOM_LIMIT_RX_PWR_HS FAST_MODE -#define UFS_QCOM_LIMIT_TX_PWR_HS FAST_MODE -#define UFS_QCOM_LIMIT_HS_RATE PA_HS_MODE_B -#define UFS_QCOM_LIMIT_DESIRED_MODE FAST - -/* QCOM UFS host controller vendor specific registers */ -enum { - REG_UFS_SYS1CLK_1US = 0xC0, - REG_UFS_TX_SYMBOL_CLK_NS_US = 0xC4, - REG_UFS_LOCAL_PORT_ID_REG = 0xC8, - REG_UFS_PA_ERR_CODE = 0xCC, - REG_UFS_RETRY_TIMER_REG = 0xD0, - REG_UFS_PA_LINK_STARTUP_TIMER = 0xD8, - REG_UFS_CFG1 = 0xDC, - REG_UFS_CFG2 = 0xE0, - REG_UFS_HW_VERSION = 0xE4, - - UFS_TEST_BUS = 0xE8, - UFS_TEST_BUS_CTRL_0 = 0xEC, - UFS_TEST_BUS_CTRL_1 = 0xF0, - UFS_TEST_BUS_CTRL_2 = 0xF4, - UFS_UNIPRO_CFG = 0xF8, - - /* - * QCOM UFS host controller vendor specific registers - * added in HW Version 3.0.0 - */ - UFS_AH8_CFG = 0xFC, -}; - -/* QCOM UFS host controller vendor specific debug registers */ -enum { - UFS_DBG_RD_REG_UAWM = 0x100, - UFS_DBG_RD_REG_UARM = 0x200, - UFS_DBG_RD_REG_TXUC = 0x300, - UFS_DBG_RD_REG_RXUC = 0x400, - UFS_DBG_RD_REG_DFC = 0x500, - UFS_DBG_RD_REG_TRLUT = 0x600, - UFS_DBG_RD_REG_TMRLUT = 0x700, - UFS_UFS_DBG_RD_REG_OCSC = 0x800, - - UFS_UFS_DBG_RD_DESC_RAM = 0x1500, - UFS_UFS_DBG_RD_PRDT_RAM = 0x1700, - UFS_UFS_DBG_RD_RESP_RAM = 0x1800, - UFS_UFS_DBG_RD_EDTL_RAM = 0x1900, -}; - -#define UFS_CNTLR_2_x_x_VEN_REGS_OFFSET(x) (0x000 + x) -#define UFS_CNTLR_3_x_x_VEN_REGS_OFFSET(x) (0x400 + x) - -/* bit definitions for REG_UFS_CFG1 register */ -#define QUNIPRO_SEL UFS_BIT(0) -#define TEST_BUS_EN BIT(18) -#define TEST_BUS_SEL GENMASK(22, 19) - -/* bit definitions for REG_UFS_CFG2 register */ -#define UAWM_HW_CGC_EN (1 << 0) -#define UARM_HW_CGC_EN (1 << 1) -#define TXUC_HW_CGC_EN (1 << 2) -#define RXUC_HW_CGC_EN (1 << 3) -#define DFC_HW_CGC_EN (1 << 4) -#define TRLUT_HW_CGC_EN (1 << 5) -#define TMRLUT_HW_CGC_EN (1 << 6) -#define OCSC_HW_CGC_EN (1 << 7) - -/* bit definition for UFS_UFS_TEST_BUS_CTRL_n */ -#define TEST_BUS_SUB_SEL_MASK 0x1F /* All XXX_SEL fields are 5 bits wide */ - -#define REG_UFS_CFG2_CGC_EN_ALL (UAWM_HW_CGC_EN | UARM_HW_CGC_EN |\ - TXUC_HW_CGC_EN | RXUC_HW_CGC_EN |\ - DFC_HW_CGC_EN | TRLUT_HW_CGC_EN |\ - TMRLUT_HW_CGC_EN | OCSC_HW_CGC_EN) - -/* bit offset */ -enum { - OFFSET_UFS_PHY_SOFT_RESET = 1, - OFFSET_CLK_NS_REG = 10, -}; - -/* bit masks */ -enum { - MASK_UFS_PHY_SOFT_RESET = 0x2, - MASK_TX_SYMBOL_CLK_1US_REG = 0x3FF, - MASK_CLK_NS_REG = 0xFFFC00, -}; - -enum ufs_qcom_phy_init_type { - UFS_PHY_INIT_FULL, - UFS_PHY_INIT_CFG_RESTORE, -}; - -/* QCOM UFS debug print bit mask */ -#define UFS_QCOM_DBG_PRINT_REGS_EN BIT(0) -#define UFS_QCOM_DBG_PRINT_ICE_REGS_EN BIT(1) -#define UFS_QCOM_DBG_PRINT_TEST_BUS_EN BIT(2) - -#define UFS_QCOM_DBG_PRINT_ALL \ - (UFS_QCOM_DBG_PRINT_REGS_EN | UFS_QCOM_DBG_PRINT_ICE_REGS_EN | \ - UFS_QCOM_DBG_PRINT_TEST_BUS_EN) - -/* QUniPro Vendor specific attributes */ -#define DME_VS_CORE_CLK_CTRL 0xD002 -/* bit and mask definitions for DME_VS_CORE_CLK_CTRL attribute */ -#define DME_VS_CORE_CLK_CTRL_CORE_CLK_DIV_EN_BIT BIT(8) -#define DME_VS_CORE_CLK_CTRL_MAX_CORE_CLK_1US_CYCLES_MASK 0xFF - -static inline void -ufs_qcom_get_controller_revision(struct ufs_hba *hba, - u8 *major, u16 *minor, u16 *step) -{ - u32 ver = ufshcd_readl(hba, REG_UFS_HW_VERSION); - - *major = (ver & UFS_HW_VER_MAJOR_MASK) >> UFS_HW_VER_MAJOR_SHFT; - *minor = (ver & UFS_HW_VER_MINOR_MASK) >> UFS_HW_VER_MINOR_SHFT; - *step = (ver & UFS_HW_VER_STEP_MASK) >> UFS_HW_VER_STEP_SHFT; -}; - -static inline void ufs_qcom_assert_reset(struct ufs_hba *hba) -{ - ufshcd_rmwl(hba, MASK_UFS_PHY_SOFT_RESET, - 1 << OFFSET_UFS_PHY_SOFT_RESET, REG_UFS_CFG1); - - /* - * Make sure assertion of ufs phy reset is written to - * register before returning - */ - mb(); -} - -static inline void ufs_qcom_deassert_reset(struct ufs_hba *hba) -{ - ufshcd_rmwl(hba, MASK_UFS_PHY_SOFT_RESET, - 0 << OFFSET_UFS_PHY_SOFT_RESET, REG_UFS_CFG1); - - /* - * Make sure de-assertion of ufs phy reset is written to - * register before returning - */ - mb(); -} - -struct ufs_qcom_bus_vote { - uint32_t client_handle; - uint32_t curr_vote; - int min_bw_vote; - int max_bw_vote; - int saved_vote; - bool is_max_bw_needed; - struct device_attribute max_bus_bw; -}; - -/* Host controller hardware version: major.minor.step */ -struct ufs_hw_version { - u16 step; - u16 minor; - u8 major; -}; - -struct ufs_qcom_testbus { - u8 select_major; - u8 select_minor; -}; - -struct ufs_qcom_host { - /* - * Set this capability if host controller supports the QUniPro mode - * and if driver wants the Host controller to operate in QUniPro mode. - * Note: By default this capability will be kept enabled if host - * controller supports the QUniPro mode. - */ - #define UFS_QCOM_CAP_QUNIPRO UFS_BIT(0) - - /* - * Set this capability if host controller can retain the secure - * configuration even after UFS controller core power collapse. - */ - #define UFS_QCOM_CAP_RETAIN_SEC_CFG_AFTER_PWR_COLLAPSE UFS_BIT(1) - u32 caps; - - struct phy *generic_phy; - struct ufs_hba *hba; - struct ufs_qcom_bus_vote bus_vote; - struct ufs_pa_layer_attr dev_req_params; - struct clk *rx_l0_sync_clk; - struct clk *tx_l0_sync_clk; - struct clk *rx_l1_sync_clk; - struct clk *tx_l1_sync_clk; - bool is_lane_clks_enabled; - - void __iomem *dev_ref_clk_ctrl_mmio; - bool is_dev_ref_clk_enabled; - struct ufs_hw_version hw_ver; - - u32 dev_ref_clk_en_mask; - - /* Bitmask for enabling debug prints */ - u32 dbg_print_en; - struct ufs_qcom_testbus testbus; -}; - -#define ufs_qcom_is_link_off(hba) ufshcd_is_link_off(hba) -#define ufs_qcom_is_link_active(hba) ufshcd_is_link_active(hba) -#define ufs_qcom_is_link_hibern8(hba) ufshcd_is_link_hibern8(hba) - -int ufs_qcom_testbus_config(struct ufs_qcom_host *host); - -static inline bool ufs_qcom_cap_qunipro(struct ufs_qcom_host *host) -{ - if (host->caps & UFS_QCOM_CAP_QUNIPRO) - return true; - else - return false; -} - -#endif /* UFS_QCOM_H_ */ diff --git a/include/linux/phy/phy-qcom-ufs.h~HEAD b/include/linux/phy/phy-qcom-ufs.h~HEAD deleted file mode 100644 index 9d18e9f948e9..000000000000 --- a/include/linux/phy/phy-qcom-ufs.h~HEAD +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2013-2015, Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#ifndef PHY_QCOM_UFS_H_ -#define PHY_QCOM_UFS_H_ - -#include "phy.h" - -/** - * ufs_qcom_phy_enable_ref_clk() - Enable the phy - * ref clock. - * @phy: reference to a generic phy - * - * returns 0 for success, and non-zero for error. - */ -int ufs_qcom_phy_enable_ref_clk(struct phy *phy); - -/** - * ufs_qcom_phy_disable_ref_clk() - Disable the phy - * ref clock. - * @phy: reference to a generic phy. - */ -void ufs_qcom_phy_disable_ref_clk(struct phy *phy); - -/** - * ufs_qcom_phy_enable_dev_ref_clk() - Enable the device - * ref clock. - * @phy: reference to a generic phy. - */ -void ufs_qcom_phy_enable_dev_ref_clk(struct phy *phy); - -/** - * ufs_qcom_phy_disable_dev_ref_clk() - Disable the device - * ref clock. - * @phy: reference to a generic phy. - */ -void ufs_qcom_phy_disable_dev_ref_clk(struct phy *phy); - -int ufs_qcom_phy_enable_iface_clk(struct phy *phy); -void ufs_qcom_phy_disable_iface_clk(struct phy *phy); -int ufs_qcom_phy_start_serdes(struct phy *phy); -int ufs_qcom_phy_set_tx_lane_enable(struct phy *phy, u32 tx_lanes); -int ufs_qcom_phy_calibrate_phy(struct phy *phy, bool is_rate_B); -int ufs_qcom_phy_is_pcs_ready(struct phy *phy); -void ufs_qcom_phy_save_controller_version(struct phy *phy, - u8 major, u16 minor, u16 step); - -#endif /* PHY_QCOM_UFS_H_ */