18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * HiSilicon Hixxxx UFS Driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2016-2017 Linaro Ltd. 68c2ecf20Sopenharmony_ci * Copyright (c) 2016-2017 HiSilicon Technologies Co., Ltd. 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/time.h> 108c2ecf20Sopenharmony_ci#include <linux/of.h> 118c2ecf20Sopenharmony_ci#include <linux/of_address.h> 128c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h> 138c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 148c2ecf20Sopenharmony_ci#include <linux/reset.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include "ufshcd.h" 178c2ecf20Sopenharmony_ci#include "ufshcd-pltfrm.h" 188c2ecf20Sopenharmony_ci#include "unipro.h" 198c2ecf20Sopenharmony_ci#include "ufs-hisi.h" 208c2ecf20Sopenharmony_ci#include "ufshci.h" 218c2ecf20Sopenharmony_ci#include "ufs_quirks.h" 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_cistatic int ufs_hisi_check_hibern8(struct ufs_hba *hba) 248c2ecf20Sopenharmony_ci{ 258c2ecf20Sopenharmony_ci int err = 0; 268c2ecf20Sopenharmony_ci u32 tx_fsm_val_0 = 0; 278c2ecf20Sopenharmony_ci u32 tx_fsm_val_1 = 0; 288c2ecf20Sopenharmony_ci unsigned long timeout = jiffies + msecs_to_jiffies(HBRN8_POLL_TOUT_MS); 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci do { 318c2ecf20Sopenharmony_ci err = ufshcd_dme_get(hba, UIC_ARG_MIB_SEL(MPHY_TX_FSM_STATE, 0), 328c2ecf20Sopenharmony_ci &tx_fsm_val_0); 338c2ecf20Sopenharmony_ci err |= ufshcd_dme_get(hba, 348c2ecf20Sopenharmony_ci UIC_ARG_MIB_SEL(MPHY_TX_FSM_STATE, 1), &tx_fsm_val_1); 358c2ecf20Sopenharmony_ci if (err || (tx_fsm_val_0 == TX_FSM_HIBERN8 && 368c2ecf20Sopenharmony_ci tx_fsm_val_1 == TX_FSM_HIBERN8)) 378c2ecf20Sopenharmony_ci break; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci /* sleep for max. 200us */ 408c2ecf20Sopenharmony_ci usleep_range(100, 200); 418c2ecf20Sopenharmony_ci } while (time_before(jiffies, timeout)); 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci /* 448c2ecf20Sopenharmony_ci * we might have scheduled out for long during polling so 458c2ecf20Sopenharmony_ci * check the state again. 468c2ecf20Sopenharmony_ci */ 478c2ecf20Sopenharmony_ci if (time_after(jiffies, timeout)) { 488c2ecf20Sopenharmony_ci err = ufshcd_dme_get(hba, UIC_ARG_MIB_SEL(MPHY_TX_FSM_STATE, 0), 498c2ecf20Sopenharmony_ci &tx_fsm_val_0); 508c2ecf20Sopenharmony_ci err |= ufshcd_dme_get(hba, 518c2ecf20Sopenharmony_ci UIC_ARG_MIB_SEL(MPHY_TX_FSM_STATE, 1), &tx_fsm_val_1); 528c2ecf20Sopenharmony_ci } 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci if (err) { 558c2ecf20Sopenharmony_ci dev_err(hba->dev, "%s: unable to get TX_FSM_STATE, err %d\n", 568c2ecf20Sopenharmony_ci __func__, err); 578c2ecf20Sopenharmony_ci } else if (tx_fsm_val_0 != TX_FSM_HIBERN8 || 588c2ecf20Sopenharmony_ci tx_fsm_val_1 != TX_FSM_HIBERN8) { 598c2ecf20Sopenharmony_ci err = -1; 608c2ecf20Sopenharmony_ci dev_err(hba->dev, "%s: invalid TX_FSM_STATE, lane0 = %d, lane1 = %d\n", 618c2ecf20Sopenharmony_ci __func__, tx_fsm_val_0, tx_fsm_val_1); 628c2ecf20Sopenharmony_ci } 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci return err; 658c2ecf20Sopenharmony_ci} 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistatic void ufs_hisi_clk_init(struct ufs_hba *hba) 688c2ecf20Sopenharmony_ci{ 698c2ecf20Sopenharmony_ci struct ufs_hisi_host *host = ufshcd_get_variant(hba); 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci ufs_sys_ctrl_clr_bits(host, BIT_SYSCTRL_REF_CLOCK_EN, PHY_CLK_CTRL); 728c2ecf20Sopenharmony_ci if (ufs_sys_ctrl_readl(host, PHY_CLK_CTRL) & BIT_SYSCTRL_REF_CLOCK_EN) 738c2ecf20Sopenharmony_ci mdelay(1); 748c2ecf20Sopenharmony_ci /* use abb clk */ 758c2ecf20Sopenharmony_ci ufs_sys_ctrl_clr_bits(host, BIT_UFS_REFCLK_SRC_SEl, UFS_SYSCTRL); 768c2ecf20Sopenharmony_ci ufs_sys_ctrl_clr_bits(host, BIT_UFS_REFCLK_ISO_EN, PHY_ISO_EN); 778c2ecf20Sopenharmony_ci /* open mphy ref clk */ 788c2ecf20Sopenharmony_ci ufs_sys_ctrl_set_bits(host, BIT_SYSCTRL_REF_CLOCK_EN, PHY_CLK_CTRL); 798c2ecf20Sopenharmony_ci} 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_cistatic void ufs_hisi_soc_init(struct ufs_hba *hba) 828c2ecf20Sopenharmony_ci{ 838c2ecf20Sopenharmony_ci struct ufs_hisi_host *host = ufshcd_get_variant(hba); 848c2ecf20Sopenharmony_ci u32 reg; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci if (!IS_ERR(host->rst)) 878c2ecf20Sopenharmony_ci reset_control_assert(host->rst); 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci /* HC_PSW powerup */ 908c2ecf20Sopenharmony_ci ufs_sys_ctrl_set_bits(host, BIT_UFS_PSW_MTCMOS_EN, PSW_POWER_CTRL); 918c2ecf20Sopenharmony_ci udelay(10); 928c2ecf20Sopenharmony_ci /* notify PWR ready */ 938c2ecf20Sopenharmony_ci ufs_sys_ctrl_set_bits(host, BIT_SYSCTRL_PWR_READY, HC_LP_CTRL); 948c2ecf20Sopenharmony_ci ufs_sys_ctrl_writel(host, MASK_UFS_DEVICE_RESET | 0, 958c2ecf20Sopenharmony_ci UFS_DEVICE_RESET_CTRL); 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci reg = ufs_sys_ctrl_readl(host, PHY_CLK_CTRL); 988c2ecf20Sopenharmony_ci reg = (reg & ~MASK_SYSCTRL_CFG_CLOCK_FREQ) | UFS_FREQ_CFG_CLK; 998c2ecf20Sopenharmony_ci /* set cfg clk freq */ 1008c2ecf20Sopenharmony_ci ufs_sys_ctrl_writel(host, reg, PHY_CLK_CTRL); 1018c2ecf20Sopenharmony_ci /* set ref clk freq */ 1028c2ecf20Sopenharmony_ci ufs_sys_ctrl_clr_bits(host, MASK_SYSCTRL_REF_CLOCK_SEL, PHY_CLK_CTRL); 1038c2ecf20Sopenharmony_ci /* bypass ufs clk gate */ 1048c2ecf20Sopenharmony_ci ufs_sys_ctrl_set_bits(host, MASK_UFS_CLK_GATE_BYPASS, 1058c2ecf20Sopenharmony_ci CLOCK_GATE_BYPASS); 1068c2ecf20Sopenharmony_ci ufs_sys_ctrl_set_bits(host, MASK_UFS_SYSCRTL_BYPASS, UFS_SYSCTRL); 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci /* open psw clk */ 1098c2ecf20Sopenharmony_ci ufs_sys_ctrl_set_bits(host, BIT_SYSCTRL_PSW_CLK_EN, PSW_CLK_CTRL); 1108c2ecf20Sopenharmony_ci /* disable ufshc iso */ 1118c2ecf20Sopenharmony_ci ufs_sys_ctrl_clr_bits(host, BIT_UFS_PSW_ISO_CTRL, PSW_POWER_CTRL); 1128c2ecf20Sopenharmony_ci /* disable phy iso */ 1138c2ecf20Sopenharmony_ci ufs_sys_ctrl_clr_bits(host, BIT_UFS_PHY_ISO_CTRL, PHY_ISO_EN); 1148c2ecf20Sopenharmony_ci /* notice iso disable */ 1158c2ecf20Sopenharmony_ci ufs_sys_ctrl_clr_bits(host, BIT_SYSCTRL_LP_ISOL_EN, HC_LP_CTRL); 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci /* disable lp_reset_n */ 1188c2ecf20Sopenharmony_ci ufs_sys_ctrl_set_bits(host, BIT_SYSCTRL_LP_RESET_N, RESET_CTRL_EN); 1198c2ecf20Sopenharmony_ci mdelay(1); 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci ufs_sys_ctrl_writel(host, MASK_UFS_DEVICE_RESET | BIT_UFS_DEVICE_RESET, 1228c2ecf20Sopenharmony_ci UFS_DEVICE_RESET_CTRL); 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci msleep(20); 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci /* 1278c2ecf20Sopenharmony_ci * enable the fix of linereset recovery, 1288c2ecf20Sopenharmony_ci * and enable rx_reset/tx_rest beat 1298c2ecf20Sopenharmony_ci * enable ref_clk_en override(bit5) & 1308c2ecf20Sopenharmony_ci * override value = 1(bit4), with mask 1318c2ecf20Sopenharmony_ci */ 1328c2ecf20Sopenharmony_ci ufs_sys_ctrl_writel(host, 0x03300330, UFS_DEVICE_RESET_CTRL); 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci if (!IS_ERR(host->rst)) 1358c2ecf20Sopenharmony_ci reset_control_deassert(host->rst); 1368c2ecf20Sopenharmony_ci} 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_cistatic int ufs_hisi_link_startup_pre_change(struct ufs_hba *hba) 1398c2ecf20Sopenharmony_ci{ 1408c2ecf20Sopenharmony_ci struct ufs_hisi_host *host = ufshcd_get_variant(hba); 1418c2ecf20Sopenharmony_ci int err; 1428c2ecf20Sopenharmony_ci uint32_t value; 1438c2ecf20Sopenharmony_ci uint32_t reg; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci /* Unipro VS_mphy_disable */ 1468c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xD0C1, 0x0), 0x1); 1478c2ecf20Sopenharmony_ci /* PA_HSSeries */ 1488c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x156A, 0x0), 0x2); 1498c2ecf20Sopenharmony_ci /* MPHY CBRATESEL */ 1508c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x8114, 0x0), 0x1); 1518c2ecf20Sopenharmony_ci /* MPHY CBOVRCTRL2 */ 1528c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x8121, 0x0), 0x2D); 1538c2ecf20Sopenharmony_ci /* MPHY CBOVRCTRL3 */ 1548c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x8122, 0x0), 0x1); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci if (host->caps & UFS_HISI_CAP_PHY10nm) { 1578c2ecf20Sopenharmony_ci /* MPHY CBOVRCTRL4 */ 1588c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x8127, 0x0), 0x98); 1598c2ecf20Sopenharmony_ci /* MPHY CBOVRCTRL5 */ 1608c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x8128, 0x0), 0x1); 1618c2ecf20Sopenharmony_ci } 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci /* Unipro VS_MphyCfgUpdt */ 1648c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xD085, 0x0), 0x1); 1658c2ecf20Sopenharmony_ci /* MPHY RXOVRCTRL4 rx0 */ 1668c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x800D, 0x4), 0x58); 1678c2ecf20Sopenharmony_ci /* MPHY RXOVRCTRL4 rx1 */ 1688c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x800D, 0x5), 0x58); 1698c2ecf20Sopenharmony_ci /* MPHY RXOVRCTRL5 rx0 */ 1708c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x800E, 0x4), 0xB); 1718c2ecf20Sopenharmony_ci /* MPHY RXOVRCTRL5 rx1 */ 1728c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x800E, 0x5), 0xB); 1738c2ecf20Sopenharmony_ci /* MPHY RXSQCONTROL rx0 */ 1748c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x8009, 0x4), 0x1); 1758c2ecf20Sopenharmony_ci /* MPHY RXSQCONTROL rx1 */ 1768c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x8009, 0x5), 0x1); 1778c2ecf20Sopenharmony_ci /* Unipro VS_MphyCfgUpdt */ 1788c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xD085, 0x0), 0x1); 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x8113, 0x0), 0x1); 1818c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xD085, 0x0), 0x1); 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci if (host->caps & UFS_HISI_CAP_PHY10nm) { 1848c2ecf20Sopenharmony_ci /* RX_Hibern8Time_Capability*/ 1858c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x0092, 0x4), 0xA); 1868c2ecf20Sopenharmony_ci /* RX_Hibern8Time_Capability*/ 1878c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x0092, 0x5), 0xA); 1888c2ecf20Sopenharmony_ci /* RX_Min_ActivateTime */ 1898c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x008f, 0x4), 0xA); 1908c2ecf20Sopenharmony_ci /* RX_Min_ActivateTime*/ 1918c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x008f, 0x5), 0xA); 1928c2ecf20Sopenharmony_ci } else { 1938c2ecf20Sopenharmony_ci /* Tactive RX */ 1948c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x008F, 0x4), 0x7); 1958c2ecf20Sopenharmony_ci /* Tactive RX */ 1968c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x008F, 0x5), 0x7); 1978c2ecf20Sopenharmony_ci } 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci /* Gear3 Synclength */ 2008c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x0095, 0x4), 0x4F); 2018c2ecf20Sopenharmony_ci /* Gear3 Synclength */ 2028c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x0095, 0x5), 0x4F); 2038c2ecf20Sopenharmony_ci /* Gear2 Synclength */ 2048c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x0094, 0x4), 0x4F); 2058c2ecf20Sopenharmony_ci /* Gear2 Synclength */ 2068c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x0094, 0x5), 0x4F); 2078c2ecf20Sopenharmony_ci /* Gear1 Synclength */ 2088c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x008B, 0x4), 0x4F); 2098c2ecf20Sopenharmony_ci /* Gear1 Synclength */ 2108c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x008B, 0x5), 0x4F); 2118c2ecf20Sopenharmony_ci /* Thibernate Tx */ 2128c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x000F, 0x0), 0x5); 2138c2ecf20Sopenharmony_ci /* Thibernate Tx */ 2148c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x000F, 0x1), 0x5); 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xD085, 0x0), 0x1); 2178c2ecf20Sopenharmony_ci /* Unipro VS_mphy_disable */ 2188c2ecf20Sopenharmony_ci ufshcd_dme_get(hba, UIC_ARG_MIB_SEL(0xD0C1, 0x0), &value); 2198c2ecf20Sopenharmony_ci if (value != 0x1) 2208c2ecf20Sopenharmony_ci dev_info(hba->dev, 2218c2ecf20Sopenharmony_ci "Warring!!! Unipro VS_mphy_disable is 0x%x\n", value); 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci /* Unipro VS_mphy_disable */ 2248c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xD0C1, 0x0), 0x0); 2258c2ecf20Sopenharmony_ci err = ufs_hisi_check_hibern8(hba); 2268c2ecf20Sopenharmony_ci if (err) 2278c2ecf20Sopenharmony_ci dev_err(hba->dev, "ufs_hisi_check_hibern8 error\n"); 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci if (!(host->caps & UFS_HISI_CAP_PHY10nm)) 2308c2ecf20Sopenharmony_ci ufshcd_writel(hba, UFS_HCLKDIV_NORMAL_VALUE, UFS_REG_HCLKDIV); 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci /* disable auto H8 */ 2338c2ecf20Sopenharmony_ci reg = ufshcd_readl(hba, REG_AUTO_HIBERNATE_IDLE_TIMER); 2348c2ecf20Sopenharmony_ci reg = reg & (~UFS_AHIT_AH8ITV_MASK); 2358c2ecf20Sopenharmony_ci ufshcd_writel(hba, reg, REG_AUTO_HIBERNATE_IDLE_TIMER); 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci /* Unipro PA_Local_TX_LCC_Enable */ 2388c2ecf20Sopenharmony_ci ufshcd_disable_host_tx_lcc(hba); 2398c2ecf20Sopenharmony_ci /* close Unipro VS_Mk2ExtnSupport */ 2408c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xD0AB, 0x0), 0x0); 2418c2ecf20Sopenharmony_ci ufshcd_dme_get(hba, UIC_ARG_MIB_SEL(0xD0AB, 0x0), &value); 2428c2ecf20Sopenharmony_ci if (value != 0) { 2438c2ecf20Sopenharmony_ci /* Ensure close success */ 2448c2ecf20Sopenharmony_ci dev_info(hba->dev, "WARN: close VS_Mk2ExtnSupport failed\n"); 2458c2ecf20Sopenharmony_ci } 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci return err; 2488c2ecf20Sopenharmony_ci} 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_cistatic int ufs_hisi_link_startup_post_change(struct ufs_hba *hba) 2518c2ecf20Sopenharmony_ci{ 2528c2ecf20Sopenharmony_ci struct ufs_hisi_host *host = ufshcd_get_variant(hba); 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci /* Unipro DL_AFC0CreditThreshold */ 2558c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB(0x2044), 0x0); 2568c2ecf20Sopenharmony_ci /* Unipro DL_TC0OutAckThreshold */ 2578c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB(0x2045), 0x0); 2588c2ecf20Sopenharmony_ci /* Unipro DL_TC0TXFCThreshold */ 2598c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB(0x2040), 0x9); 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci /* not bypass ufs clk gate */ 2628c2ecf20Sopenharmony_ci ufs_sys_ctrl_clr_bits(host, MASK_UFS_CLK_GATE_BYPASS, 2638c2ecf20Sopenharmony_ci CLOCK_GATE_BYPASS); 2648c2ecf20Sopenharmony_ci ufs_sys_ctrl_clr_bits(host, MASK_UFS_SYSCRTL_BYPASS, 2658c2ecf20Sopenharmony_ci UFS_SYSCTRL); 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci /* select received symbol cnt */ 2688c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB(0xd09a), 0x80000000); 2698c2ecf20Sopenharmony_ci /* reset counter0 and enable */ 2708c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB(0xd09c), 0x00000005); 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci return 0; 2738c2ecf20Sopenharmony_ci} 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_cistatic int ufs_hisi_link_startup_notify(struct ufs_hba *hba, 2768c2ecf20Sopenharmony_ci enum ufs_notify_change_status status) 2778c2ecf20Sopenharmony_ci{ 2788c2ecf20Sopenharmony_ci int err = 0; 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci switch (status) { 2818c2ecf20Sopenharmony_ci case PRE_CHANGE: 2828c2ecf20Sopenharmony_ci err = ufs_hisi_link_startup_pre_change(hba); 2838c2ecf20Sopenharmony_ci break; 2848c2ecf20Sopenharmony_ci case POST_CHANGE: 2858c2ecf20Sopenharmony_ci err = ufs_hisi_link_startup_post_change(hba); 2868c2ecf20Sopenharmony_ci break; 2878c2ecf20Sopenharmony_ci default: 2888c2ecf20Sopenharmony_ci break; 2898c2ecf20Sopenharmony_ci } 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci return err; 2928c2ecf20Sopenharmony_ci} 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_cistatic void ufs_hisi_set_dev_cap(struct ufs_dev_params *hisi_param) 2958c2ecf20Sopenharmony_ci{ 2968c2ecf20Sopenharmony_ci hisi_param->rx_lanes = UFS_HISI_LIMIT_NUM_LANES_RX; 2978c2ecf20Sopenharmony_ci hisi_param->tx_lanes = UFS_HISI_LIMIT_NUM_LANES_TX; 2988c2ecf20Sopenharmony_ci hisi_param->hs_rx_gear = UFS_HISI_LIMIT_HSGEAR_RX; 2998c2ecf20Sopenharmony_ci hisi_param->hs_tx_gear = UFS_HISI_LIMIT_HSGEAR_TX; 3008c2ecf20Sopenharmony_ci hisi_param->pwm_rx_gear = UFS_HISI_LIMIT_PWMGEAR_RX; 3018c2ecf20Sopenharmony_ci hisi_param->pwm_tx_gear = UFS_HISI_LIMIT_PWMGEAR_TX; 3028c2ecf20Sopenharmony_ci hisi_param->rx_pwr_pwm = UFS_HISI_LIMIT_RX_PWR_PWM; 3038c2ecf20Sopenharmony_ci hisi_param->tx_pwr_pwm = UFS_HISI_LIMIT_TX_PWR_PWM; 3048c2ecf20Sopenharmony_ci hisi_param->rx_pwr_hs = UFS_HISI_LIMIT_RX_PWR_HS; 3058c2ecf20Sopenharmony_ci hisi_param->tx_pwr_hs = UFS_HISI_LIMIT_TX_PWR_HS; 3068c2ecf20Sopenharmony_ci hisi_param->hs_rate = UFS_HISI_LIMIT_HS_RATE; 3078c2ecf20Sopenharmony_ci hisi_param->desired_working_mode = UFS_HISI_LIMIT_DESIRED_MODE; 3088c2ecf20Sopenharmony_ci} 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_cistatic void ufs_hisi_pwr_change_pre_change(struct ufs_hba *hba) 3118c2ecf20Sopenharmony_ci{ 3128c2ecf20Sopenharmony_ci struct ufs_hisi_host *host = ufshcd_get_variant(hba); 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci if (host->caps & UFS_HISI_CAP_PHY10nm) { 3158c2ecf20Sopenharmony_ci /* 3168c2ecf20Sopenharmony_ci * Boston platform need to set SaveConfigTime to 0x13, 3178c2ecf20Sopenharmony_ci * and change sync length to maximum value 3188c2ecf20Sopenharmony_ci */ 3198c2ecf20Sopenharmony_ci /* VS_DebugSaveConfigTime */ 3208c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB((u32)0xD0A0), 0x13); 3218c2ecf20Sopenharmony_ci /* g1 sync length */ 3228c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB((u32)0x1552), 0x4f); 3238c2ecf20Sopenharmony_ci /* g2 sync length */ 3248c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB((u32)0x1554), 0x4f); 3258c2ecf20Sopenharmony_ci /* g3 sync length */ 3268c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB((u32)0x1556), 0x4f); 3278c2ecf20Sopenharmony_ci /* PA_Hibern8Time */ 3288c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB((u32)0x15a7), 0xA); 3298c2ecf20Sopenharmony_ci /* PA_Tactivate */ 3308c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB((u32)0x15a8), 0xA); 3318c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xd085, 0x0), 0x01); 3328c2ecf20Sopenharmony_ci } 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci if (hba->dev_quirks & UFS_DEVICE_QUIRK_HOST_VS_DEBUGSAVECONFIGTIME) { 3358c2ecf20Sopenharmony_ci pr_info("ufs flash device must set VS_DebugSaveConfigTime 0x10\n"); 3368c2ecf20Sopenharmony_ci /* VS_DebugSaveConfigTime */ 3378c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB(0xD0A0), 0x10); 3388c2ecf20Sopenharmony_ci /* sync length */ 3398c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB(0x1556), 0x48); 3408c2ecf20Sopenharmony_ci } 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci /* update */ 3438c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB(0x15A8), 0x1); 3448c2ecf20Sopenharmony_ci /* PA_TxSkip */ 3458c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB(0x155c), 0x0); 3468c2ecf20Sopenharmony_ci /*PA_PWRModeUserData0 = 8191, default is 0*/ 3478c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b0), 8191); 3488c2ecf20Sopenharmony_ci /*PA_PWRModeUserData1 = 65535, default is 0*/ 3498c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b1), 65535); 3508c2ecf20Sopenharmony_ci /*PA_PWRModeUserData2 = 32767, default is 0*/ 3518c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b2), 32767); 3528c2ecf20Sopenharmony_ci /*DME_FC0ProtectionTimeOutVal = 8191, default is 0*/ 3538c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB(0xd041), 8191); 3548c2ecf20Sopenharmony_ci /*DME_TC0ReplayTimeOutVal = 65535, default is 0*/ 3558c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB(0xd042), 65535); 3568c2ecf20Sopenharmony_ci /*DME_AFC0ReqTimeOutVal = 32767, default is 0*/ 3578c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB(0xd043), 32767); 3588c2ecf20Sopenharmony_ci /*PA_PWRModeUserData3 = 8191, default is 0*/ 3598c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b3), 8191); 3608c2ecf20Sopenharmony_ci /*PA_PWRModeUserData4 = 65535, default is 0*/ 3618c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b4), 65535); 3628c2ecf20Sopenharmony_ci /*PA_PWRModeUserData5 = 32767, default is 0*/ 3638c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b5), 32767); 3648c2ecf20Sopenharmony_ci /*DME_FC1ProtectionTimeOutVal = 8191, default is 0*/ 3658c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB(0xd044), 8191); 3668c2ecf20Sopenharmony_ci /*DME_TC1ReplayTimeOutVal = 65535, default is 0*/ 3678c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB(0xd045), 65535); 3688c2ecf20Sopenharmony_ci /*DME_AFC1ReqTimeOutVal = 32767, default is 0*/ 3698c2ecf20Sopenharmony_ci ufshcd_dme_set(hba, UIC_ARG_MIB(0xd046), 32767); 3708c2ecf20Sopenharmony_ci} 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_cistatic int ufs_hisi_pwr_change_notify(struct ufs_hba *hba, 3738c2ecf20Sopenharmony_ci enum ufs_notify_change_status status, 3748c2ecf20Sopenharmony_ci struct ufs_pa_layer_attr *dev_max_params, 3758c2ecf20Sopenharmony_ci struct ufs_pa_layer_attr *dev_req_params) 3768c2ecf20Sopenharmony_ci{ 3778c2ecf20Sopenharmony_ci struct ufs_dev_params ufs_hisi_cap; 3788c2ecf20Sopenharmony_ci int ret = 0; 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci if (!dev_req_params) { 3818c2ecf20Sopenharmony_ci dev_err(hba->dev, 3828c2ecf20Sopenharmony_ci "%s: incoming dev_req_params is NULL\n", __func__); 3838c2ecf20Sopenharmony_ci ret = -EINVAL; 3848c2ecf20Sopenharmony_ci goto out; 3858c2ecf20Sopenharmony_ci } 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci switch (status) { 3888c2ecf20Sopenharmony_ci case PRE_CHANGE: 3898c2ecf20Sopenharmony_ci ufs_hisi_set_dev_cap(&ufs_hisi_cap); 3908c2ecf20Sopenharmony_ci ret = ufshcd_get_pwr_dev_param(&ufs_hisi_cap, 3918c2ecf20Sopenharmony_ci dev_max_params, dev_req_params); 3928c2ecf20Sopenharmony_ci if (ret) { 3938c2ecf20Sopenharmony_ci dev_err(hba->dev, 3948c2ecf20Sopenharmony_ci "%s: failed to determine capabilities\n", __func__); 3958c2ecf20Sopenharmony_ci goto out; 3968c2ecf20Sopenharmony_ci } 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci ufs_hisi_pwr_change_pre_change(hba); 3998c2ecf20Sopenharmony_ci break; 4008c2ecf20Sopenharmony_ci case POST_CHANGE: 4018c2ecf20Sopenharmony_ci break; 4028c2ecf20Sopenharmony_ci default: 4038c2ecf20Sopenharmony_ci ret = -EINVAL; 4048c2ecf20Sopenharmony_ci break; 4058c2ecf20Sopenharmony_ci } 4068c2ecf20Sopenharmony_ciout: 4078c2ecf20Sopenharmony_ci return ret; 4088c2ecf20Sopenharmony_ci} 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_cistatic int ufs_hisi_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) 4118c2ecf20Sopenharmony_ci{ 4128c2ecf20Sopenharmony_ci struct ufs_hisi_host *host = ufshcd_get_variant(hba); 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci if (ufshcd_is_runtime_pm(pm_op)) 4158c2ecf20Sopenharmony_ci return 0; 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci if (host->in_suspend) { 4188c2ecf20Sopenharmony_ci WARN_ON(1); 4198c2ecf20Sopenharmony_ci return 0; 4208c2ecf20Sopenharmony_ci } 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci ufs_sys_ctrl_clr_bits(host, BIT_SYSCTRL_REF_CLOCK_EN, PHY_CLK_CTRL); 4238c2ecf20Sopenharmony_ci udelay(10); 4248c2ecf20Sopenharmony_ci /* set ref_dig_clk override of PHY PCS to 0 */ 4258c2ecf20Sopenharmony_ci ufs_sys_ctrl_writel(host, 0x00100000, UFS_DEVICE_RESET_CTRL); 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci host->in_suspend = true; 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci return 0; 4308c2ecf20Sopenharmony_ci} 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_cistatic int ufs_hisi_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) 4338c2ecf20Sopenharmony_ci{ 4348c2ecf20Sopenharmony_ci struct ufs_hisi_host *host = ufshcd_get_variant(hba); 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci if (!host->in_suspend) 4378c2ecf20Sopenharmony_ci return 0; 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci /* set ref_dig_clk override of PHY PCS to 1 */ 4408c2ecf20Sopenharmony_ci ufs_sys_ctrl_writel(host, 0x00100010, UFS_DEVICE_RESET_CTRL); 4418c2ecf20Sopenharmony_ci udelay(10); 4428c2ecf20Sopenharmony_ci ufs_sys_ctrl_set_bits(host, BIT_SYSCTRL_REF_CLOCK_EN, PHY_CLK_CTRL); 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci host->in_suspend = false; 4458c2ecf20Sopenharmony_ci return 0; 4468c2ecf20Sopenharmony_ci} 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_cistatic int ufs_hisi_get_resource(struct ufs_hisi_host *host) 4498c2ecf20Sopenharmony_ci{ 4508c2ecf20Sopenharmony_ci struct device *dev = host->hba->dev; 4518c2ecf20Sopenharmony_ci struct platform_device *pdev = to_platform_device(dev); 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci /* get resource of ufs sys ctrl */ 4548c2ecf20Sopenharmony_ci host->ufs_sys_ctrl = devm_platform_ioremap_resource(pdev, 1); 4558c2ecf20Sopenharmony_ci return PTR_ERR_OR_ZERO(host->ufs_sys_ctrl); 4568c2ecf20Sopenharmony_ci} 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_cistatic void ufs_hisi_set_pm_lvl(struct ufs_hba *hba) 4598c2ecf20Sopenharmony_ci{ 4608c2ecf20Sopenharmony_ci hba->rpm_lvl = UFS_PM_LVL_1; 4618c2ecf20Sopenharmony_ci hba->spm_lvl = UFS_PM_LVL_3; 4628c2ecf20Sopenharmony_ci} 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci/** 4658c2ecf20Sopenharmony_ci * ufs_hisi_init_common 4668c2ecf20Sopenharmony_ci * @hba: host controller instance 4678c2ecf20Sopenharmony_ci */ 4688c2ecf20Sopenharmony_cistatic int ufs_hisi_init_common(struct ufs_hba *hba) 4698c2ecf20Sopenharmony_ci{ 4708c2ecf20Sopenharmony_ci int err = 0; 4718c2ecf20Sopenharmony_ci struct device *dev = hba->dev; 4728c2ecf20Sopenharmony_ci struct ufs_hisi_host *host; 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL); 4758c2ecf20Sopenharmony_ci if (!host) 4768c2ecf20Sopenharmony_ci return -ENOMEM; 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci host->hba = hba; 4798c2ecf20Sopenharmony_ci ufshcd_set_variant(hba, host); 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci host->rst = devm_reset_control_get(dev, "rst"); 4828c2ecf20Sopenharmony_ci if (IS_ERR(host->rst)) { 4838c2ecf20Sopenharmony_ci dev_err(dev, "%s: failed to get reset control\n", __func__); 4848c2ecf20Sopenharmony_ci err = PTR_ERR(host->rst); 4858c2ecf20Sopenharmony_ci goto error; 4868c2ecf20Sopenharmony_ci } 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci ufs_hisi_set_pm_lvl(hba); 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci err = ufs_hisi_get_resource(host); 4918c2ecf20Sopenharmony_ci if (err) 4928c2ecf20Sopenharmony_ci goto error; 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci return 0; 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_cierror: 4978c2ecf20Sopenharmony_ci ufshcd_set_variant(hba, NULL); 4988c2ecf20Sopenharmony_ci return err; 4998c2ecf20Sopenharmony_ci} 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_cistatic int ufs_hi3660_init(struct ufs_hba *hba) 5028c2ecf20Sopenharmony_ci{ 5038c2ecf20Sopenharmony_ci int ret = 0; 5048c2ecf20Sopenharmony_ci struct device *dev = hba->dev; 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ci ret = ufs_hisi_init_common(hba); 5078c2ecf20Sopenharmony_ci if (ret) { 5088c2ecf20Sopenharmony_ci dev_err(dev, "%s: ufs common init fail\n", __func__); 5098c2ecf20Sopenharmony_ci return ret; 5108c2ecf20Sopenharmony_ci } 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci ufs_hisi_clk_init(hba); 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci ufs_hisi_soc_init(hba); 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ci return 0; 5178c2ecf20Sopenharmony_ci} 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_cistatic int ufs_hi3670_init(struct ufs_hba *hba) 5208c2ecf20Sopenharmony_ci{ 5218c2ecf20Sopenharmony_ci int ret = 0; 5228c2ecf20Sopenharmony_ci struct device *dev = hba->dev; 5238c2ecf20Sopenharmony_ci struct ufs_hisi_host *host; 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci ret = ufs_hisi_init_common(hba); 5268c2ecf20Sopenharmony_ci if (ret) { 5278c2ecf20Sopenharmony_ci dev_err(dev, "%s: ufs common init fail\n", __func__); 5288c2ecf20Sopenharmony_ci return ret; 5298c2ecf20Sopenharmony_ci } 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_ci ufs_hisi_clk_init(hba); 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci ufs_hisi_soc_init(hba); 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci /* Add cap for 10nm PHY variant on HI3670 SoC */ 5368c2ecf20Sopenharmony_ci host = ufshcd_get_variant(hba); 5378c2ecf20Sopenharmony_ci host->caps |= UFS_HISI_CAP_PHY10nm; 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci return 0; 5408c2ecf20Sopenharmony_ci} 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_cistatic const struct ufs_hba_variant_ops ufs_hba_hi3660_vops = { 5438c2ecf20Sopenharmony_ci .name = "hi3660", 5448c2ecf20Sopenharmony_ci .init = ufs_hi3660_init, 5458c2ecf20Sopenharmony_ci .link_startup_notify = ufs_hisi_link_startup_notify, 5468c2ecf20Sopenharmony_ci .pwr_change_notify = ufs_hisi_pwr_change_notify, 5478c2ecf20Sopenharmony_ci .suspend = ufs_hisi_suspend, 5488c2ecf20Sopenharmony_ci .resume = ufs_hisi_resume, 5498c2ecf20Sopenharmony_ci}; 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_cistatic const struct ufs_hba_variant_ops ufs_hba_hi3670_vops = { 5528c2ecf20Sopenharmony_ci .name = "hi3670", 5538c2ecf20Sopenharmony_ci .init = ufs_hi3670_init, 5548c2ecf20Sopenharmony_ci .link_startup_notify = ufs_hisi_link_startup_notify, 5558c2ecf20Sopenharmony_ci .pwr_change_notify = ufs_hisi_pwr_change_notify, 5568c2ecf20Sopenharmony_ci .suspend = ufs_hisi_suspend, 5578c2ecf20Sopenharmony_ci .resume = ufs_hisi_resume, 5588c2ecf20Sopenharmony_ci}; 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_cistatic const struct of_device_id ufs_hisi_of_match[] = { 5618c2ecf20Sopenharmony_ci { .compatible = "hisilicon,hi3660-ufs", .data = &ufs_hba_hi3660_vops }, 5628c2ecf20Sopenharmony_ci { .compatible = "hisilicon,hi3670-ufs", .data = &ufs_hba_hi3670_vops }, 5638c2ecf20Sopenharmony_ci {}, 5648c2ecf20Sopenharmony_ci}; 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, ufs_hisi_of_match); 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_cistatic int ufs_hisi_probe(struct platform_device *pdev) 5698c2ecf20Sopenharmony_ci{ 5708c2ecf20Sopenharmony_ci const struct of_device_id *of_id; 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci of_id = of_match_node(ufs_hisi_of_match, pdev->dev.of_node); 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci return ufshcd_pltfrm_init(pdev, of_id->data); 5758c2ecf20Sopenharmony_ci} 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_cistatic int ufs_hisi_remove(struct platform_device *pdev) 5788c2ecf20Sopenharmony_ci{ 5798c2ecf20Sopenharmony_ci struct ufs_hba *hba = platform_get_drvdata(pdev); 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci ufshcd_remove(hba); 5828c2ecf20Sopenharmony_ci return 0; 5838c2ecf20Sopenharmony_ci} 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_cistatic const struct dev_pm_ops ufs_hisi_pm_ops = { 5868c2ecf20Sopenharmony_ci .suspend = ufshcd_pltfrm_suspend, 5878c2ecf20Sopenharmony_ci .resume = ufshcd_pltfrm_resume, 5888c2ecf20Sopenharmony_ci .runtime_suspend = ufshcd_pltfrm_runtime_suspend, 5898c2ecf20Sopenharmony_ci .runtime_resume = ufshcd_pltfrm_runtime_resume, 5908c2ecf20Sopenharmony_ci .runtime_idle = ufshcd_pltfrm_runtime_idle, 5918c2ecf20Sopenharmony_ci}; 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_cistatic struct platform_driver ufs_hisi_pltform = { 5948c2ecf20Sopenharmony_ci .probe = ufs_hisi_probe, 5958c2ecf20Sopenharmony_ci .remove = ufs_hisi_remove, 5968c2ecf20Sopenharmony_ci .shutdown = ufshcd_pltfrm_shutdown, 5978c2ecf20Sopenharmony_ci .driver = { 5988c2ecf20Sopenharmony_ci .name = "ufshcd-hisi", 5998c2ecf20Sopenharmony_ci .pm = &ufs_hisi_pm_ops, 6008c2ecf20Sopenharmony_ci .of_match_table = of_match_ptr(ufs_hisi_of_match), 6018c2ecf20Sopenharmony_ci }, 6028c2ecf20Sopenharmony_ci}; 6038c2ecf20Sopenharmony_cimodule_platform_driver(ufs_hisi_pltform); 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 6068c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:ufshcd-hisi"); 6078c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("HiSilicon Hixxxx UFS Driver"); 608