1*dd11376bSBart Van Assche // SPDX-License-Identifier: GPL-2.0-only 2*dd11376bSBart Van Assche /* 3*dd11376bSBart Van Assche * UFS Host Controller driver for Exynos specific extensions 4*dd11376bSBart Van Assche * 5*dd11376bSBart Van Assche * Copyright (C) 2014-2015 Samsung Electronics Co., Ltd. 6*dd11376bSBart Van Assche * Author: Seungwon Jeon <essuuj@gmail.com> 7*dd11376bSBart Van Assche * Author: Alim Akhtar <alim.akhtar@samsung.com> 8*dd11376bSBart Van Assche * 9*dd11376bSBart Van Assche */ 10*dd11376bSBart Van Assche 11*dd11376bSBart Van Assche #include <linux/clk.h> 12*dd11376bSBart Van Assche #include <linux/delay.h> 13*dd11376bSBart Van Assche #include <linux/module.h> 14*dd11376bSBart Van Assche #include <linux/of.h> 15*dd11376bSBart Van Assche #include <linux/of_address.h> 16*dd11376bSBart Van Assche #include <linux/mfd/syscon.h> 17*dd11376bSBart Van Assche #include <linux/phy/phy.h> 18*dd11376bSBart Van Assche #include <linux/platform_device.h> 19*dd11376bSBart Van Assche #include <linux/regmap.h> 20*dd11376bSBart Van Assche 21*dd11376bSBart Van Assche #include <ufs/ufshcd.h> 22*dd11376bSBart Van Assche #include "ufshcd-pltfrm.h" 23*dd11376bSBart Van Assche #include <ufs/ufshci.h> 24*dd11376bSBart Van Assche #include <ufs/unipro.h> 25*dd11376bSBart Van Assche 26*dd11376bSBart Van Assche #include "ufs-exynos.h" 27*dd11376bSBart Van Assche 28*dd11376bSBart Van Assche /* 29*dd11376bSBart Van Assche * Exynos's Vendor specific registers for UFSHCI 30*dd11376bSBart Van Assche */ 31*dd11376bSBart Van Assche #define HCI_TXPRDT_ENTRY_SIZE 0x00 32*dd11376bSBart Van Assche #define PRDT_PREFECT_EN BIT(31) 33*dd11376bSBart Van Assche #define PRDT_SET_SIZE(x) ((x) & 0x1F) 34*dd11376bSBart Van Assche #define HCI_RXPRDT_ENTRY_SIZE 0x04 35*dd11376bSBart Van Assche #define HCI_1US_TO_CNT_VAL 0x0C 36*dd11376bSBart Van Assche #define CNT_VAL_1US_MASK 0x3FF 37*dd11376bSBart Van Assche #define HCI_UTRL_NEXUS_TYPE 0x40 38*dd11376bSBart Van Assche #define HCI_UTMRL_NEXUS_TYPE 0x44 39*dd11376bSBart Van Assche #define HCI_SW_RST 0x50 40*dd11376bSBart Van Assche #define UFS_LINK_SW_RST BIT(0) 41*dd11376bSBart Van Assche #define UFS_UNIPRO_SW_RST BIT(1) 42*dd11376bSBart Van Assche #define UFS_SW_RST_MASK (UFS_UNIPRO_SW_RST | UFS_LINK_SW_RST) 43*dd11376bSBart Van Assche #define HCI_DATA_REORDER 0x60 44*dd11376bSBart Van Assche #define HCI_UNIPRO_APB_CLK_CTRL 0x68 45*dd11376bSBart Van Assche #define UNIPRO_APB_CLK(v, x) (((v) & ~0xF) | ((x) & 0xF)) 46*dd11376bSBart Van Assche #define HCI_AXIDMA_RWDATA_BURST_LEN 0x6C 47*dd11376bSBart Van Assche #define HCI_GPIO_OUT 0x70 48*dd11376bSBart Van Assche #define HCI_ERR_EN_PA_LAYER 0x78 49*dd11376bSBart Van Assche #define HCI_ERR_EN_DL_LAYER 0x7C 50*dd11376bSBart Van Assche #define HCI_ERR_EN_N_LAYER 0x80 51*dd11376bSBart Van Assche #define HCI_ERR_EN_T_LAYER 0x84 52*dd11376bSBart Van Assche #define HCI_ERR_EN_DME_LAYER 0x88 53*dd11376bSBart Van Assche #define HCI_CLKSTOP_CTRL 0xB0 54*dd11376bSBart Van Assche #define REFCLKOUT_STOP BIT(4) 55*dd11376bSBart Van Assche #define REFCLK_STOP BIT(2) 56*dd11376bSBart Van Assche #define UNIPRO_MCLK_STOP BIT(1) 57*dd11376bSBart Van Assche #define UNIPRO_PCLK_STOP BIT(0) 58*dd11376bSBart Van Assche #define CLK_STOP_MASK (REFCLKOUT_STOP | REFCLK_STOP |\ 59*dd11376bSBart Van Assche UNIPRO_MCLK_STOP |\ 60*dd11376bSBart Van Assche UNIPRO_PCLK_STOP) 61*dd11376bSBart Van Assche #define HCI_MISC 0xB4 62*dd11376bSBart Van Assche #define REFCLK_CTRL_EN BIT(7) 63*dd11376bSBart Van Assche #define UNIPRO_PCLK_CTRL_EN BIT(6) 64*dd11376bSBart Van Assche #define UNIPRO_MCLK_CTRL_EN BIT(5) 65*dd11376bSBart Van Assche #define HCI_CORECLK_CTRL_EN BIT(4) 66*dd11376bSBart Van Assche #define CLK_CTRL_EN_MASK (REFCLK_CTRL_EN |\ 67*dd11376bSBart Van Assche UNIPRO_PCLK_CTRL_EN |\ 68*dd11376bSBart Van Assche UNIPRO_MCLK_CTRL_EN) 69*dd11376bSBart Van Assche /* Device fatal error */ 70*dd11376bSBart Van Assche #define DFES_ERR_EN BIT(31) 71*dd11376bSBart Van Assche #define DFES_DEF_L2_ERRS (UIC_DATA_LINK_LAYER_ERROR_RX_BUF_OF |\ 72*dd11376bSBart Van Assche UIC_DATA_LINK_LAYER_ERROR_PA_INIT) 73*dd11376bSBart Van Assche #define DFES_DEF_L3_ERRS (UIC_NETWORK_UNSUPPORTED_HEADER_TYPE |\ 74*dd11376bSBart Van Assche UIC_NETWORK_BAD_DEVICEID_ENC |\ 75*dd11376bSBart Van Assche UIC_NETWORK_LHDR_TRAP_PACKET_DROPPING) 76*dd11376bSBart Van Assche #define DFES_DEF_L4_ERRS (UIC_TRANSPORT_UNSUPPORTED_HEADER_TYPE |\ 77*dd11376bSBart Van Assche UIC_TRANSPORT_UNKNOWN_CPORTID |\ 78*dd11376bSBart Van Assche UIC_TRANSPORT_NO_CONNECTION_RX |\ 79*dd11376bSBart Van Assche UIC_TRANSPORT_BAD_TC) 80*dd11376bSBart Van Assche 81*dd11376bSBart Van Assche /* FSYS UFS Shareability */ 82*dd11376bSBart Van Assche #define UFS_WR_SHARABLE BIT(2) 83*dd11376bSBart Van Assche #define UFS_RD_SHARABLE BIT(1) 84*dd11376bSBart Van Assche #define UFS_SHARABLE (UFS_WR_SHARABLE | UFS_RD_SHARABLE) 85*dd11376bSBart Van Assche #define UFS_SHAREABILITY_OFFSET 0x710 86*dd11376bSBart Van Assche 87*dd11376bSBart Van Assche /* Multi-host registers */ 88*dd11376bSBart Van Assche #define MHCTRL 0xC4 89*dd11376bSBart Van Assche #define MHCTRL_EN_VH_MASK (0xE) 90*dd11376bSBart Van Assche #define MHCTRL_EN_VH(vh) (vh << 1) 91*dd11376bSBart Van Assche #define PH2VH_MBOX 0xD8 92*dd11376bSBart Van Assche 93*dd11376bSBart Van Assche #define MH_MSG_MASK (0xFF) 94*dd11376bSBart Van Assche 95*dd11376bSBart Van Assche #define MH_MSG(id, msg) ((id << 8) | (msg & 0xFF)) 96*dd11376bSBart Van Assche #define MH_MSG_PH_READY 0x1 97*dd11376bSBart Van Assche #define MH_MSG_VH_READY 0x2 98*dd11376bSBart Van Assche 99*dd11376bSBart Van Assche #define ALLOW_INQUIRY BIT(25) 100*dd11376bSBart Van Assche #define ALLOW_MODE_SELECT BIT(24) 101*dd11376bSBart Van Assche #define ALLOW_MODE_SENSE BIT(23) 102*dd11376bSBart Van Assche #define ALLOW_PRE_FETCH GENMASK(22, 21) 103*dd11376bSBart Van Assche #define ALLOW_READ_CMD_ALL GENMASK(20, 18) /* read_6/10/16 */ 104*dd11376bSBart Van Assche #define ALLOW_READ_BUFFER BIT(17) 105*dd11376bSBart Van Assche #define ALLOW_READ_CAPACITY GENMASK(16, 15) 106*dd11376bSBart Van Assche #define ALLOW_REPORT_LUNS BIT(14) 107*dd11376bSBart Van Assche #define ALLOW_REQUEST_SENSE BIT(13) 108*dd11376bSBart Van Assche #define ALLOW_SYNCHRONIZE_CACHE GENMASK(8, 7) 109*dd11376bSBart Van Assche #define ALLOW_TEST_UNIT_READY BIT(6) 110*dd11376bSBart Van Assche #define ALLOW_UNMAP BIT(5) 111*dd11376bSBart Van Assche #define ALLOW_VERIFY BIT(4) 112*dd11376bSBart Van Assche #define ALLOW_WRITE_CMD_ALL GENMASK(3, 1) /* write_6/10/16 */ 113*dd11376bSBart Van Assche 114*dd11376bSBart Van Assche #define ALLOW_TRANS_VH_DEFAULT (ALLOW_INQUIRY | ALLOW_MODE_SELECT | \ 115*dd11376bSBart Van Assche ALLOW_MODE_SENSE | ALLOW_PRE_FETCH | \ 116*dd11376bSBart Van Assche ALLOW_READ_CMD_ALL | ALLOW_READ_BUFFER | \ 117*dd11376bSBart Van Assche ALLOW_READ_CAPACITY | ALLOW_REPORT_LUNS | \ 118*dd11376bSBart Van Assche ALLOW_REQUEST_SENSE | ALLOW_SYNCHRONIZE_CACHE | \ 119*dd11376bSBart Van Assche ALLOW_TEST_UNIT_READY | ALLOW_UNMAP | \ 120*dd11376bSBart Van Assche ALLOW_VERIFY | ALLOW_WRITE_CMD_ALL) 121*dd11376bSBart Van Assche 122*dd11376bSBart Van Assche #define HCI_MH_ALLOWABLE_TRAN_OF_VH 0x30C 123*dd11376bSBart Van Assche #define HCI_MH_IID_IN_TASK_TAG 0X308 124*dd11376bSBart Van Assche 125*dd11376bSBart Van Assche #define PH_READY_TIMEOUT_MS (5 * MSEC_PER_SEC) 126*dd11376bSBart Van Assche 127*dd11376bSBart Van Assche enum { 128*dd11376bSBart Van Assche UNIPRO_L1_5 = 0,/* PHY Adapter */ 129*dd11376bSBart Van Assche UNIPRO_L2, /* Data Link */ 130*dd11376bSBart Van Assche UNIPRO_L3, /* Network */ 131*dd11376bSBart Van Assche UNIPRO_L4, /* Transport */ 132*dd11376bSBart Van Assche UNIPRO_DME, /* DME */ 133*dd11376bSBart Van Assche }; 134*dd11376bSBart Van Assche 135*dd11376bSBart Van Assche /* 136*dd11376bSBart Van Assche * UNIPRO registers 137*dd11376bSBart Van Assche */ 138*dd11376bSBart Van Assche #define UNIPRO_COMP_VERSION 0x000 139*dd11376bSBart Van Assche #define UNIPRO_DME_PWR_REQ 0x090 140*dd11376bSBart Van Assche #define UNIPRO_DME_PWR_REQ_POWERMODE 0x094 141*dd11376bSBart Van Assche #define UNIPRO_DME_PWR_REQ_LOCALL2TIMER0 0x098 142*dd11376bSBart Van Assche #define UNIPRO_DME_PWR_REQ_LOCALL2TIMER1 0x09C 143*dd11376bSBart Van Assche #define UNIPRO_DME_PWR_REQ_LOCALL2TIMER2 0x0A0 144*dd11376bSBart Van Assche #define UNIPRO_DME_PWR_REQ_REMOTEL2TIMER0 0x0A4 145*dd11376bSBart Van Assche #define UNIPRO_DME_PWR_REQ_REMOTEL2TIMER1 0x0A8 146*dd11376bSBart Van Assche #define UNIPRO_DME_PWR_REQ_REMOTEL2TIMER2 0x0AC 147*dd11376bSBart Van Assche 148*dd11376bSBart Van Assche /* 149*dd11376bSBart Van Assche * UFS Protector registers 150*dd11376bSBart Van Assche */ 151*dd11376bSBart Van Assche #define UFSPRSECURITY 0x010 152*dd11376bSBart Van Assche #define NSSMU BIT(14) 153*dd11376bSBart Van Assche #define UFSPSBEGIN0 0x200 154*dd11376bSBart Van Assche #define UFSPSEND0 0x204 155*dd11376bSBart Van Assche #define UFSPSLUN0 0x208 156*dd11376bSBart Van Assche #define UFSPSCTRL0 0x20C 157*dd11376bSBart Van Assche 158*dd11376bSBart Van Assche #define CNTR_DIV_VAL 40 159*dd11376bSBart Van Assche 160*dd11376bSBart Van Assche static struct exynos_ufs_drv_data exynos_ufs_drvs; 161*dd11376bSBart Van Assche static void exynos_ufs_auto_ctrl_hcc(struct exynos_ufs *ufs, bool en); 162*dd11376bSBart Van Assche static void exynos_ufs_ctrl_clkstop(struct exynos_ufs *ufs, bool en); 163*dd11376bSBart Van Assche 164*dd11376bSBart Van Assche static inline void exynos_ufs_enable_auto_ctrl_hcc(struct exynos_ufs *ufs) 165*dd11376bSBart Van Assche { 166*dd11376bSBart Van Assche exynos_ufs_auto_ctrl_hcc(ufs, true); 167*dd11376bSBart Van Assche } 168*dd11376bSBart Van Assche 169*dd11376bSBart Van Assche static inline void exynos_ufs_disable_auto_ctrl_hcc(struct exynos_ufs *ufs) 170*dd11376bSBart Van Assche { 171*dd11376bSBart Van Assche exynos_ufs_auto_ctrl_hcc(ufs, false); 172*dd11376bSBart Van Assche } 173*dd11376bSBart Van Assche 174*dd11376bSBart Van Assche static inline void exynos_ufs_disable_auto_ctrl_hcc_save( 175*dd11376bSBart Van Assche struct exynos_ufs *ufs, u32 *val) 176*dd11376bSBart Van Assche { 177*dd11376bSBart Van Assche *val = hci_readl(ufs, HCI_MISC); 178*dd11376bSBart Van Assche exynos_ufs_auto_ctrl_hcc(ufs, false); 179*dd11376bSBart Van Assche } 180*dd11376bSBart Van Assche 181*dd11376bSBart Van Assche static inline void exynos_ufs_auto_ctrl_hcc_restore( 182*dd11376bSBart Van Assche struct exynos_ufs *ufs, u32 *val) 183*dd11376bSBart Van Assche { 184*dd11376bSBart Van Assche hci_writel(ufs, *val, HCI_MISC); 185*dd11376bSBart Van Assche } 186*dd11376bSBart Van Assche 187*dd11376bSBart Van Assche static inline void exynos_ufs_gate_clks(struct exynos_ufs *ufs) 188*dd11376bSBart Van Assche { 189*dd11376bSBart Van Assche exynos_ufs_ctrl_clkstop(ufs, true); 190*dd11376bSBart Van Assche } 191*dd11376bSBart Van Assche 192*dd11376bSBart Van Assche static inline void exynos_ufs_ungate_clks(struct exynos_ufs *ufs) 193*dd11376bSBart Van Assche { 194*dd11376bSBart Van Assche exynos_ufs_ctrl_clkstop(ufs, false); 195*dd11376bSBart Van Assche } 196*dd11376bSBart Van Assche 197*dd11376bSBart Van Assche static int exynos7_ufs_drv_init(struct device *dev, struct exynos_ufs *ufs) 198*dd11376bSBart Van Assche { 199*dd11376bSBart Van Assche return 0; 200*dd11376bSBart Van Assche } 201*dd11376bSBart Van Assche 202*dd11376bSBart Van Assche static int exynosauto_ufs_drv_init(struct device *dev, struct exynos_ufs *ufs) 203*dd11376bSBart Van Assche { 204*dd11376bSBart Van Assche struct exynos_ufs_uic_attr *attr = ufs->drv_data->uic_attr; 205*dd11376bSBart Van Assche 206*dd11376bSBart Van Assche /* IO Coherency setting */ 207*dd11376bSBart Van Assche if (ufs->sysreg) { 208*dd11376bSBart Van Assche return regmap_update_bits(ufs->sysreg, 209*dd11376bSBart Van Assche ufs->shareability_reg_offset, 210*dd11376bSBart Van Assche UFS_SHARABLE, UFS_SHARABLE); 211*dd11376bSBart Van Assche } 212*dd11376bSBart Van Assche 213*dd11376bSBart Van Assche attr->tx_dif_p_nsec = 3200000; 214*dd11376bSBart Van Assche 215*dd11376bSBart Van Assche return 0; 216*dd11376bSBart Van Assche } 217*dd11376bSBart Van Assche 218*dd11376bSBart Van Assche static int exynosauto_ufs_post_hce_enable(struct exynos_ufs *ufs) 219*dd11376bSBart Van Assche { 220*dd11376bSBart Van Assche struct ufs_hba *hba = ufs->hba; 221*dd11376bSBart Van Assche 222*dd11376bSBart Van Assche /* Enable Virtual Host #1 */ 223*dd11376bSBart Van Assche ufshcd_rmwl(hba, MHCTRL_EN_VH_MASK, MHCTRL_EN_VH(1), MHCTRL); 224*dd11376bSBart Van Assche /* Default VH Transfer permissions */ 225*dd11376bSBart Van Assche hci_writel(ufs, ALLOW_TRANS_VH_DEFAULT, HCI_MH_ALLOWABLE_TRAN_OF_VH); 226*dd11376bSBart Van Assche /* IID information is replaced in TASKTAG[7:5] instead of IID in UCD */ 227*dd11376bSBart Van Assche hci_writel(ufs, 0x1, HCI_MH_IID_IN_TASK_TAG); 228*dd11376bSBart Van Assche 229*dd11376bSBart Van Assche return 0; 230*dd11376bSBart Van Assche } 231*dd11376bSBart Van Assche 232*dd11376bSBart Van Assche static int exynosauto_ufs_pre_link(struct exynos_ufs *ufs) 233*dd11376bSBart Van Assche { 234*dd11376bSBart Van Assche struct ufs_hba *hba = ufs->hba; 235*dd11376bSBart Van Assche int i; 236*dd11376bSBart Van Assche u32 tx_line_reset_period, rx_line_reset_period; 237*dd11376bSBart Van Assche 238*dd11376bSBart Van Assche rx_line_reset_period = (RX_LINE_RESET_TIME * ufs->mclk_rate) / NSEC_PER_MSEC; 239*dd11376bSBart Van Assche tx_line_reset_period = (TX_LINE_RESET_TIME * ufs->mclk_rate) / NSEC_PER_MSEC; 240*dd11376bSBart Van Assche 241*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB(0x200), 0x40); 242*dd11376bSBart Van Assche for_each_ufs_rx_lane(ufs, i) { 243*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(VND_RX_CLK_PRD, i), 244*dd11376bSBart Van Assche DIV_ROUND_UP(NSEC_PER_SEC, ufs->mclk_rate)); 245*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(VND_RX_CLK_PRD_EN, i), 0x0); 246*dd11376bSBart Van Assche 247*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(VND_RX_LINERESET_VALUE2, i), 248*dd11376bSBart Van Assche (rx_line_reset_period >> 16) & 0xFF); 249*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(VND_RX_LINERESET_VALUE1, i), 250*dd11376bSBart Van Assche (rx_line_reset_period >> 8) & 0xFF); 251*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(VND_RX_LINERESET_VALUE0, i), 252*dd11376bSBart Van Assche (rx_line_reset_period) & 0xFF); 253*dd11376bSBart Van Assche 254*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x2f, i), 0x79); 255*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x84, i), 0x1); 256*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x25, i), 0xf6); 257*dd11376bSBart Van Assche } 258*dd11376bSBart Van Assche 259*dd11376bSBart Van Assche for_each_ufs_tx_lane(ufs, i) { 260*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(VND_TX_CLK_PRD, i), 261*dd11376bSBart Van Assche DIV_ROUND_UP(NSEC_PER_SEC, ufs->mclk_rate)); 262*dd11376bSBart Van Assche /* Not to affect VND_TX_LINERESET_PVALUE to VND_TX_CLK_PRD */ 263*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(VND_TX_CLK_PRD_EN, i), 264*dd11376bSBart Van Assche 0x02); 265*dd11376bSBart Van Assche 266*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(VND_TX_LINERESET_PVALUE2, i), 267*dd11376bSBart Van Assche (tx_line_reset_period >> 16) & 0xFF); 268*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(VND_TX_LINERESET_PVALUE1, i), 269*dd11376bSBart Van Assche (tx_line_reset_period >> 8) & 0xFF); 270*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(VND_TX_LINERESET_PVALUE0, i), 271*dd11376bSBart Van Assche (tx_line_reset_period) & 0xFF); 272*dd11376bSBart Van Assche 273*dd11376bSBart Van Assche /* TX PWM Gear Capability / PWM_G1_ONLY */ 274*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x04, i), 0x1); 275*dd11376bSBart Van Assche } 276*dd11376bSBart Van Assche 277*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB(0x200), 0x0); 278*dd11376bSBart Van Assche 279*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE), 0x0); 280*dd11376bSBart Van Assche 281*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB(0xa011), 0x8000); 282*dd11376bSBart Van Assche 283*dd11376bSBart Van Assche return 0; 284*dd11376bSBart Van Assche } 285*dd11376bSBart Van Assche 286*dd11376bSBart Van Assche static int exynosauto_ufs_pre_pwr_change(struct exynos_ufs *ufs, 287*dd11376bSBart Van Assche struct ufs_pa_layer_attr *pwr) 288*dd11376bSBart Van Assche { 289*dd11376bSBart Van Assche struct ufs_hba *hba = ufs->hba; 290*dd11376bSBart Van Assche 291*dd11376bSBart Van Assche /* PACP_PWR_req and delivered to the remote DME */ 292*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA0), 12000); 293*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA1), 32000); 294*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA2), 16000); 295*dd11376bSBart Van Assche 296*dd11376bSBart Van Assche return 0; 297*dd11376bSBart Van Assche } 298*dd11376bSBart Van Assche 299*dd11376bSBart Van Assche static int exynosauto_ufs_post_pwr_change(struct exynos_ufs *ufs, 300*dd11376bSBart Van Assche struct ufs_pa_layer_attr *pwr) 301*dd11376bSBart Van Assche { 302*dd11376bSBart Van Assche struct ufs_hba *hba = ufs->hba; 303*dd11376bSBart Van Assche u32 enabled_vh; 304*dd11376bSBart Van Assche 305*dd11376bSBart Van Assche enabled_vh = ufshcd_readl(hba, MHCTRL) & MHCTRL_EN_VH_MASK; 306*dd11376bSBart Van Assche 307*dd11376bSBart Van Assche /* Send physical host ready message to virtual hosts */ 308*dd11376bSBart Van Assche ufshcd_writel(hba, MH_MSG(enabled_vh, MH_MSG_PH_READY), PH2VH_MBOX); 309*dd11376bSBart Van Assche 310*dd11376bSBart Van Assche return 0; 311*dd11376bSBart Van Assche } 312*dd11376bSBart Van Assche 313*dd11376bSBart Van Assche static int exynos7_ufs_pre_link(struct exynos_ufs *ufs) 314*dd11376bSBart Van Assche { 315*dd11376bSBart Van Assche struct ufs_hba *hba = ufs->hba; 316*dd11376bSBart Van Assche u32 val = ufs->drv_data->uic_attr->pa_dbg_option_suite; 317*dd11376bSBart Van Assche int i; 318*dd11376bSBart Van Assche 319*dd11376bSBart Van Assche exynos_ufs_enable_ov_tm(hba); 320*dd11376bSBart Van Assche for_each_ufs_tx_lane(ufs, i) 321*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x297, i), 0x17); 322*dd11376bSBart Van Assche for_each_ufs_rx_lane(ufs, i) { 323*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x362, i), 0xff); 324*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x363, i), 0x00); 325*dd11376bSBart Van Assche } 326*dd11376bSBart Van Assche exynos_ufs_disable_ov_tm(hba); 327*dd11376bSBart Van Assche 328*dd11376bSBart Van Assche for_each_ufs_tx_lane(ufs, i) 329*dd11376bSBart Van Assche ufshcd_dme_set(hba, 330*dd11376bSBart Van Assche UIC_ARG_MIB_SEL(TX_HIBERN8_CONTROL, i), 0x0); 331*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_TXPHY_CFGUPDT), 0x1); 332*dd11376bSBart Van Assche udelay(1); 333*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_OPTION_SUITE), val | (1 << 12)); 334*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_SKIP_RESET_PHY), 0x1); 335*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_SKIP_LINE_RESET), 0x1); 336*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_LINE_RESET_REQ), 0x1); 337*dd11376bSBart Van Assche udelay(1600); 338*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_OPTION_SUITE), val); 339*dd11376bSBart Van Assche 340*dd11376bSBart Van Assche return 0; 341*dd11376bSBart Van Assche } 342*dd11376bSBart Van Assche 343*dd11376bSBart Van Assche static int exynos7_ufs_post_link(struct exynos_ufs *ufs) 344*dd11376bSBart Van Assche { 345*dd11376bSBart Van Assche struct ufs_hba *hba = ufs->hba; 346*dd11376bSBart Van Assche int i; 347*dd11376bSBart Van Assche 348*dd11376bSBart Van Assche exynos_ufs_enable_ov_tm(hba); 349*dd11376bSBart Van Assche for_each_ufs_tx_lane(ufs, i) { 350*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x28b, i), 0x83); 351*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x29a, i), 0x07); 352*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x277, i), 353*dd11376bSBart Van Assche TX_LINERESET_N(exynos_ufs_calc_time_cntr(ufs, 200000))); 354*dd11376bSBart Van Assche } 355*dd11376bSBart Van Assche exynos_ufs_disable_ov_tm(hba); 356*dd11376bSBart Van Assche 357*dd11376bSBart Van Assche exynos_ufs_enable_dbg_mode(hba); 358*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB(PA_SAVECONFIGTIME), 0xbb8); 359*dd11376bSBart Van Assche exynos_ufs_disable_dbg_mode(hba); 360*dd11376bSBart Van Assche 361*dd11376bSBart Van Assche return 0; 362*dd11376bSBart Van Assche } 363*dd11376bSBart Van Assche 364*dd11376bSBart Van Assche static int exynos7_ufs_pre_pwr_change(struct exynos_ufs *ufs, 365*dd11376bSBart Van Assche struct ufs_pa_layer_attr *pwr) 366*dd11376bSBart Van Assche { 367*dd11376bSBart Van Assche unipro_writel(ufs, 0x22, UNIPRO_DBG_FORCE_DME_CTRL_STATE); 368*dd11376bSBart Van Assche 369*dd11376bSBart Van Assche return 0; 370*dd11376bSBart Van Assche } 371*dd11376bSBart Van Assche 372*dd11376bSBart Van Assche static int exynos7_ufs_post_pwr_change(struct exynos_ufs *ufs, 373*dd11376bSBart Van Assche struct ufs_pa_layer_attr *pwr) 374*dd11376bSBart Van Assche { 375*dd11376bSBart Van Assche struct ufs_hba *hba = ufs->hba; 376*dd11376bSBart Van Assche int lanes = max_t(u32, pwr->lane_rx, pwr->lane_tx); 377*dd11376bSBart Van Assche 378*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_RXPHY_CFGUPDT), 0x1); 379*dd11376bSBart Van Assche 380*dd11376bSBart Van Assche if (lanes == 1) { 381*dd11376bSBart Van Assche exynos_ufs_enable_dbg_mode(hba); 382*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB(PA_CONNECTEDTXDATALANES), 0x1); 383*dd11376bSBart Van Assche exynos_ufs_disable_dbg_mode(hba); 384*dd11376bSBart Van Assche } 385*dd11376bSBart Van Assche 386*dd11376bSBart Van Assche return 0; 387*dd11376bSBart Van Assche } 388*dd11376bSBart Van Assche 389*dd11376bSBart Van Assche /* 390*dd11376bSBart Van Assche * exynos_ufs_auto_ctrl_hcc - HCI core clock control by h/w 391*dd11376bSBart Van Assche * Control should be disabled in the below cases 392*dd11376bSBart Van Assche * - Before host controller S/W reset 393*dd11376bSBart Van Assche * - Access to UFS protector's register 394*dd11376bSBart Van Assche */ 395*dd11376bSBart Van Assche static void exynos_ufs_auto_ctrl_hcc(struct exynos_ufs *ufs, bool en) 396*dd11376bSBart Van Assche { 397*dd11376bSBart Van Assche u32 misc = hci_readl(ufs, HCI_MISC); 398*dd11376bSBart Van Assche 399*dd11376bSBart Van Assche if (en) 400*dd11376bSBart Van Assche hci_writel(ufs, misc | HCI_CORECLK_CTRL_EN, HCI_MISC); 401*dd11376bSBart Van Assche else 402*dd11376bSBart Van Assche hci_writel(ufs, misc & ~HCI_CORECLK_CTRL_EN, HCI_MISC); 403*dd11376bSBart Van Assche } 404*dd11376bSBart Van Assche 405*dd11376bSBart Van Assche static void exynos_ufs_ctrl_clkstop(struct exynos_ufs *ufs, bool en) 406*dd11376bSBart Van Assche { 407*dd11376bSBart Van Assche u32 ctrl = hci_readl(ufs, HCI_CLKSTOP_CTRL); 408*dd11376bSBart Van Assche u32 misc = hci_readl(ufs, HCI_MISC); 409*dd11376bSBart Van Assche 410*dd11376bSBart Van Assche if (en) { 411*dd11376bSBart Van Assche hci_writel(ufs, misc | CLK_CTRL_EN_MASK, HCI_MISC); 412*dd11376bSBart Van Assche hci_writel(ufs, ctrl | CLK_STOP_MASK, HCI_CLKSTOP_CTRL); 413*dd11376bSBart Van Assche } else { 414*dd11376bSBart Van Assche hci_writel(ufs, ctrl & ~CLK_STOP_MASK, HCI_CLKSTOP_CTRL); 415*dd11376bSBart Van Assche hci_writel(ufs, misc & ~CLK_CTRL_EN_MASK, HCI_MISC); 416*dd11376bSBart Van Assche } 417*dd11376bSBart Van Assche } 418*dd11376bSBart Van Assche 419*dd11376bSBart Van Assche static int exynos_ufs_get_clk_info(struct exynos_ufs *ufs) 420*dd11376bSBart Van Assche { 421*dd11376bSBart Van Assche struct ufs_hba *hba = ufs->hba; 422*dd11376bSBart Van Assche struct list_head *head = &hba->clk_list_head; 423*dd11376bSBart Van Assche struct ufs_clk_info *clki; 424*dd11376bSBart Van Assche unsigned long pclk_rate; 425*dd11376bSBart Van Assche u32 f_min, f_max; 426*dd11376bSBart Van Assche u8 div = 0; 427*dd11376bSBart Van Assche int ret = 0; 428*dd11376bSBart Van Assche 429*dd11376bSBart Van Assche if (list_empty(head)) 430*dd11376bSBart Van Assche goto out; 431*dd11376bSBart Van Assche 432*dd11376bSBart Van Assche list_for_each_entry(clki, head, list) { 433*dd11376bSBart Van Assche if (!IS_ERR(clki->clk)) { 434*dd11376bSBart Van Assche if (!strcmp(clki->name, "core_clk")) 435*dd11376bSBart Van Assche ufs->clk_hci_core = clki->clk; 436*dd11376bSBart Van Assche else if (!strcmp(clki->name, "sclk_unipro_main")) 437*dd11376bSBart Van Assche ufs->clk_unipro_main = clki->clk; 438*dd11376bSBart Van Assche } 439*dd11376bSBart Van Assche } 440*dd11376bSBart Van Assche 441*dd11376bSBart Van Assche if (!ufs->clk_hci_core || !ufs->clk_unipro_main) { 442*dd11376bSBart Van Assche dev_err(hba->dev, "failed to get clk info\n"); 443*dd11376bSBart Van Assche ret = -EINVAL; 444*dd11376bSBart Van Assche goto out; 445*dd11376bSBart Van Assche } 446*dd11376bSBart Van Assche 447*dd11376bSBart Van Assche ufs->mclk_rate = clk_get_rate(ufs->clk_unipro_main); 448*dd11376bSBart Van Assche pclk_rate = clk_get_rate(ufs->clk_hci_core); 449*dd11376bSBart Van Assche f_min = ufs->pclk_avail_min; 450*dd11376bSBart Van Assche f_max = ufs->pclk_avail_max; 451*dd11376bSBart Van Assche 452*dd11376bSBart Van Assche if (ufs->opts & EXYNOS_UFS_OPT_HAS_APB_CLK_CTRL) { 453*dd11376bSBart Van Assche do { 454*dd11376bSBart Van Assche pclk_rate /= (div + 1); 455*dd11376bSBart Van Assche 456*dd11376bSBart Van Assche if (pclk_rate <= f_max) 457*dd11376bSBart Van Assche break; 458*dd11376bSBart Van Assche div++; 459*dd11376bSBart Van Assche } while (pclk_rate >= f_min); 460*dd11376bSBart Van Assche } 461*dd11376bSBart Van Assche 462*dd11376bSBart Van Assche if (unlikely(pclk_rate < f_min || pclk_rate > f_max)) { 463*dd11376bSBart Van Assche dev_err(hba->dev, "not available pclk range %lu\n", pclk_rate); 464*dd11376bSBart Van Assche ret = -EINVAL; 465*dd11376bSBart Van Assche goto out; 466*dd11376bSBart Van Assche } 467*dd11376bSBart Van Assche 468*dd11376bSBart Van Assche ufs->pclk_rate = pclk_rate; 469*dd11376bSBart Van Assche ufs->pclk_div = div; 470*dd11376bSBart Van Assche 471*dd11376bSBart Van Assche out: 472*dd11376bSBart Van Assche return ret; 473*dd11376bSBart Van Assche } 474*dd11376bSBart Van Assche 475*dd11376bSBart Van Assche static void exynos_ufs_set_unipro_pclk_div(struct exynos_ufs *ufs) 476*dd11376bSBart Van Assche { 477*dd11376bSBart Van Assche if (ufs->opts & EXYNOS_UFS_OPT_HAS_APB_CLK_CTRL) { 478*dd11376bSBart Van Assche u32 val; 479*dd11376bSBart Van Assche 480*dd11376bSBart Van Assche val = hci_readl(ufs, HCI_UNIPRO_APB_CLK_CTRL); 481*dd11376bSBart Van Assche hci_writel(ufs, UNIPRO_APB_CLK(val, ufs->pclk_div), 482*dd11376bSBart Van Assche HCI_UNIPRO_APB_CLK_CTRL); 483*dd11376bSBart Van Assche } 484*dd11376bSBart Van Assche } 485*dd11376bSBart Van Assche 486*dd11376bSBart Van Assche static void exynos_ufs_set_pwm_clk_div(struct exynos_ufs *ufs) 487*dd11376bSBart Van Assche { 488*dd11376bSBart Van Assche struct ufs_hba *hba = ufs->hba; 489*dd11376bSBart Van Assche struct exynos_ufs_uic_attr *attr = ufs->drv_data->uic_attr; 490*dd11376bSBart Van Assche 491*dd11376bSBart Van Assche ufshcd_dme_set(hba, 492*dd11376bSBart Van Assche UIC_ARG_MIB(CMN_PWM_CLK_CTRL), attr->cmn_pwm_clk_ctrl); 493*dd11376bSBart Van Assche } 494*dd11376bSBart Van Assche 495*dd11376bSBart Van Assche static void exynos_ufs_calc_pwm_clk_div(struct exynos_ufs *ufs) 496*dd11376bSBart Van Assche { 497*dd11376bSBart Van Assche struct ufs_hba *hba = ufs->hba; 498*dd11376bSBart Van Assche struct exynos_ufs_uic_attr *attr = ufs->drv_data->uic_attr; 499*dd11376bSBart Van Assche const unsigned int div = 30, mult = 20; 500*dd11376bSBart Van Assche const unsigned long pwm_min = 3 * 1000 * 1000; 501*dd11376bSBart Van Assche const unsigned long pwm_max = 9 * 1000 * 1000; 502*dd11376bSBart Van Assche const int divs[] = {32, 16, 8, 4}; 503*dd11376bSBart Van Assche unsigned long clk = 0, _clk, clk_period; 504*dd11376bSBart Van Assche int i = 0, clk_idx = -1; 505*dd11376bSBart Van Assche 506*dd11376bSBart Van Assche clk_period = UNIPRO_PCLK_PERIOD(ufs); 507*dd11376bSBart Van Assche for (i = 0; i < ARRAY_SIZE(divs); i++) { 508*dd11376bSBart Van Assche _clk = NSEC_PER_SEC * mult / (clk_period * divs[i] * div); 509*dd11376bSBart Van Assche if (_clk >= pwm_min && _clk <= pwm_max) { 510*dd11376bSBart Van Assche if (_clk > clk) { 511*dd11376bSBart Van Assche clk_idx = i; 512*dd11376bSBart Van Assche clk = _clk; 513*dd11376bSBart Van Assche } 514*dd11376bSBart Van Assche } 515*dd11376bSBart Van Assche } 516*dd11376bSBart Van Assche 517*dd11376bSBart Van Assche if (clk_idx == -1) { 518*dd11376bSBart Van Assche ufshcd_dme_get(hba, UIC_ARG_MIB(CMN_PWM_CLK_CTRL), &clk_idx); 519*dd11376bSBart Van Assche dev_err(hba->dev, 520*dd11376bSBart Van Assche "failed to decide pwm clock divider, will not change\n"); 521*dd11376bSBart Van Assche } 522*dd11376bSBart Van Assche 523*dd11376bSBart Van Assche attr->cmn_pwm_clk_ctrl = clk_idx & PWM_CLK_CTRL_MASK; 524*dd11376bSBart Van Assche } 525*dd11376bSBart Van Assche 526*dd11376bSBart Van Assche long exynos_ufs_calc_time_cntr(struct exynos_ufs *ufs, long period) 527*dd11376bSBart Van Assche { 528*dd11376bSBart Van Assche const int precise = 10; 529*dd11376bSBart Van Assche long pclk_rate = ufs->pclk_rate; 530*dd11376bSBart Van Assche long clk_period, fraction; 531*dd11376bSBart Van Assche 532*dd11376bSBart Van Assche clk_period = UNIPRO_PCLK_PERIOD(ufs); 533*dd11376bSBart Van Assche fraction = ((NSEC_PER_SEC % pclk_rate) * precise) / pclk_rate; 534*dd11376bSBart Van Assche 535*dd11376bSBart Van Assche return (period * precise) / ((clk_period * precise) + fraction); 536*dd11376bSBart Van Assche } 537*dd11376bSBart Van Assche 538*dd11376bSBart Van Assche static void exynos_ufs_specify_phy_time_attr(struct exynos_ufs *ufs) 539*dd11376bSBart Van Assche { 540*dd11376bSBart Van Assche struct exynos_ufs_uic_attr *attr = ufs->drv_data->uic_attr; 541*dd11376bSBart Van Assche struct ufs_phy_time_cfg *t_cfg = &ufs->t_cfg; 542*dd11376bSBart Van Assche 543*dd11376bSBart Van Assche t_cfg->tx_linereset_p = 544*dd11376bSBart Van Assche exynos_ufs_calc_time_cntr(ufs, attr->tx_dif_p_nsec); 545*dd11376bSBart Van Assche t_cfg->tx_linereset_n = 546*dd11376bSBart Van Assche exynos_ufs_calc_time_cntr(ufs, attr->tx_dif_n_nsec); 547*dd11376bSBart Van Assche t_cfg->tx_high_z_cnt = 548*dd11376bSBart Van Assche exynos_ufs_calc_time_cntr(ufs, attr->tx_high_z_cnt_nsec); 549*dd11376bSBart Van Assche t_cfg->tx_base_n_val = 550*dd11376bSBart Van Assche exynos_ufs_calc_time_cntr(ufs, attr->tx_base_unit_nsec); 551*dd11376bSBart Van Assche t_cfg->tx_gran_n_val = 552*dd11376bSBart Van Assche exynos_ufs_calc_time_cntr(ufs, attr->tx_gran_unit_nsec); 553*dd11376bSBart Van Assche t_cfg->tx_sleep_cnt = 554*dd11376bSBart Van Assche exynos_ufs_calc_time_cntr(ufs, attr->tx_sleep_cnt); 555*dd11376bSBart Van Assche 556*dd11376bSBart Van Assche t_cfg->rx_linereset = 557*dd11376bSBart Van Assche exynos_ufs_calc_time_cntr(ufs, attr->rx_dif_p_nsec); 558*dd11376bSBart Van Assche t_cfg->rx_hibern8_wait = 559*dd11376bSBart Van Assche exynos_ufs_calc_time_cntr(ufs, attr->rx_hibern8_wait_nsec); 560*dd11376bSBart Van Assche t_cfg->rx_base_n_val = 561*dd11376bSBart Van Assche exynos_ufs_calc_time_cntr(ufs, attr->rx_base_unit_nsec); 562*dd11376bSBart Van Assche t_cfg->rx_gran_n_val = 563*dd11376bSBart Van Assche exynos_ufs_calc_time_cntr(ufs, attr->rx_gran_unit_nsec); 564*dd11376bSBart Van Assche t_cfg->rx_sleep_cnt = 565*dd11376bSBart Van Assche exynos_ufs_calc_time_cntr(ufs, attr->rx_sleep_cnt); 566*dd11376bSBart Van Assche t_cfg->rx_stall_cnt = 567*dd11376bSBart Van Assche exynos_ufs_calc_time_cntr(ufs, attr->rx_stall_cnt); 568*dd11376bSBart Van Assche } 569*dd11376bSBart Van Assche 570*dd11376bSBart Van Assche static void exynos_ufs_config_phy_time_attr(struct exynos_ufs *ufs) 571*dd11376bSBart Van Assche { 572*dd11376bSBart Van Assche struct ufs_hba *hba = ufs->hba; 573*dd11376bSBart Van Assche struct ufs_phy_time_cfg *t_cfg = &ufs->t_cfg; 574*dd11376bSBart Van Assche int i; 575*dd11376bSBart Van Assche 576*dd11376bSBart Van Assche exynos_ufs_set_pwm_clk_div(ufs); 577*dd11376bSBart Van Assche 578*dd11376bSBart Van Assche exynos_ufs_enable_ov_tm(hba); 579*dd11376bSBart Van Assche 580*dd11376bSBart Van Assche for_each_ufs_rx_lane(ufs, i) { 581*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RX_FILLER_ENABLE, i), 582*dd11376bSBart Van Assche ufs->drv_data->uic_attr->rx_filler_enable); 583*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RX_LINERESET_VAL, i), 584*dd11376bSBart Van Assche RX_LINERESET(t_cfg->rx_linereset)); 585*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RX_BASE_NVAL_07_00, i), 586*dd11376bSBart Van Assche RX_BASE_NVAL_L(t_cfg->rx_base_n_val)); 587*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RX_BASE_NVAL_15_08, i), 588*dd11376bSBart Van Assche RX_BASE_NVAL_H(t_cfg->rx_base_n_val)); 589*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RX_GRAN_NVAL_07_00, i), 590*dd11376bSBart Van Assche RX_GRAN_NVAL_L(t_cfg->rx_gran_n_val)); 591*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RX_GRAN_NVAL_10_08, i), 592*dd11376bSBart Van Assche RX_GRAN_NVAL_H(t_cfg->rx_gran_n_val)); 593*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RX_OV_SLEEP_CNT_TIMER, i), 594*dd11376bSBart Van Assche RX_OV_SLEEP_CNT(t_cfg->rx_sleep_cnt)); 595*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RX_OV_STALL_CNT_TIMER, i), 596*dd11376bSBart Van Assche RX_OV_STALL_CNT(t_cfg->rx_stall_cnt)); 597*dd11376bSBart Van Assche } 598*dd11376bSBart Van Assche 599*dd11376bSBart Van Assche for_each_ufs_tx_lane(ufs, i) { 600*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(TX_LINERESET_P_VAL, i), 601*dd11376bSBart Van Assche TX_LINERESET_P(t_cfg->tx_linereset_p)); 602*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(TX_HIGH_Z_CNT_07_00, i), 603*dd11376bSBart Van Assche TX_HIGH_Z_CNT_L(t_cfg->tx_high_z_cnt)); 604*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(TX_HIGH_Z_CNT_11_08, i), 605*dd11376bSBart Van Assche TX_HIGH_Z_CNT_H(t_cfg->tx_high_z_cnt)); 606*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(TX_BASE_NVAL_07_00, i), 607*dd11376bSBart Van Assche TX_BASE_NVAL_L(t_cfg->tx_base_n_val)); 608*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(TX_BASE_NVAL_15_08, i), 609*dd11376bSBart Van Assche TX_BASE_NVAL_H(t_cfg->tx_base_n_val)); 610*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(TX_GRAN_NVAL_07_00, i), 611*dd11376bSBart Van Assche TX_GRAN_NVAL_L(t_cfg->tx_gran_n_val)); 612*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(TX_GRAN_NVAL_10_08, i), 613*dd11376bSBart Van Assche TX_GRAN_NVAL_H(t_cfg->tx_gran_n_val)); 614*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(TX_OV_SLEEP_CNT_TIMER, i), 615*dd11376bSBart Van Assche TX_OV_H8_ENTER_EN | 616*dd11376bSBart Van Assche TX_OV_SLEEP_CNT(t_cfg->tx_sleep_cnt)); 617*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(TX_MIN_ACTIVATETIME, i), 618*dd11376bSBart Van Assche ufs->drv_data->uic_attr->tx_min_activatetime); 619*dd11376bSBart Van Assche } 620*dd11376bSBart Van Assche 621*dd11376bSBart Van Assche exynos_ufs_disable_ov_tm(hba); 622*dd11376bSBart Van Assche } 623*dd11376bSBart Van Assche 624*dd11376bSBart Van Assche static void exynos_ufs_config_phy_cap_attr(struct exynos_ufs *ufs) 625*dd11376bSBart Van Assche { 626*dd11376bSBart Van Assche struct ufs_hba *hba = ufs->hba; 627*dd11376bSBart Van Assche struct exynos_ufs_uic_attr *attr = ufs->drv_data->uic_attr; 628*dd11376bSBart Van Assche int i; 629*dd11376bSBart Van Assche 630*dd11376bSBart Van Assche exynos_ufs_enable_ov_tm(hba); 631*dd11376bSBart Van Assche 632*dd11376bSBart Van Assche for_each_ufs_rx_lane(ufs, i) { 633*dd11376bSBart Van Assche ufshcd_dme_set(hba, 634*dd11376bSBart Van Assche UIC_ARG_MIB_SEL(RX_HS_G1_SYNC_LENGTH_CAP, i), 635*dd11376bSBart Van Assche attr->rx_hs_g1_sync_len_cap); 636*dd11376bSBart Van Assche ufshcd_dme_set(hba, 637*dd11376bSBart Van Assche UIC_ARG_MIB_SEL(RX_HS_G2_SYNC_LENGTH_CAP, i), 638*dd11376bSBart Van Assche attr->rx_hs_g2_sync_len_cap); 639*dd11376bSBart Van Assche ufshcd_dme_set(hba, 640*dd11376bSBart Van Assche UIC_ARG_MIB_SEL(RX_HS_G3_SYNC_LENGTH_CAP, i), 641*dd11376bSBart Van Assche attr->rx_hs_g3_sync_len_cap); 642*dd11376bSBart Van Assche ufshcd_dme_set(hba, 643*dd11376bSBart Van Assche UIC_ARG_MIB_SEL(RX_HS_G1_PREP_LENGTH_CAP, i), 644*dd11376bSBart Van Assche attr->rx_hs_g1_prep_sync_len_cap); 645*dd11376bSBart Van Assche ufshcd_dme_set(hba, 646*dd11376bSBart Van Assche UIC_ARG_MIB_SEL(RX_HS_G2_PREP_LENGTH_CAP, i), 647*dd11376bSBart Van Assche attr->rx_hs_g2_prep_sync_len_cap); 648*dd11376bSBart Van Assche ufshcd_dme_set(hba, 649*dd11376bSBart Van Assche UIC_ARG_MIB_SEL(RX_HS_G3_PREP_LENGTH_CAP, i), 650*dd11376bSBart Van Assche attr->rx_hs_g3_prep_sync_len_cap); 651*dd11376bSBart Van Assche } 652*dd11376bSBart Van Assche 653*dd11376bSBart Van Assche if (attr->rx_adv_fine_gran_sup_en == 0) { 654*dd11376bSBart Van Assche for_each_ufs_rx_lane(ufs, i) { 655*dd11376bSBart Van Assche ufshcd_dme_set(hba, 656*dd11376bSBart Van Assche UIC_ARG_MIB_SEL(RX_ADV_GRANULARITY_CAP, i), 0); 657*dd11376bSBart Van Assche 658*dd11376bSBart Van Assche if (attr->rx_min_actv_time_cap) 659*dd11376bSBart Van Assche ufshcd_dme_set(hba, 660*dd11376bSBart Van Assche UIC_ARG_MIB_SEL(RX_MIN_ACTIVATETIME_CAP, 661*dd11376bSBart Van Assche i), attr->rx_min_actv_time_cap); 662*dd11376bSBart Van Assche 663*dd11376bSBart Van Assche if (attr->rx_hibern8_time_cap) 664*dd11376bSBart Van Assche ufshcd_dme_set(hba, 665*dd11376bSBart Van Assche UIC_ARG_MIB_SEL(RX_HIBERN8TIME_CAP, i), 666*dd11376bSBart Van Assche attr->rx_hibern8_time_cap); 667*dd11376bSBart Van Assche } 668*dd11376bSBart Van Assche } else if (attr->rx_adv_fine_gran_sup_en == 1) { 669*dd11376bSBart Van Assche for_each_ufs_rx_lane(ufs, i) { 670*dd11376bSBart Van Assche if (attr->rx_adv_fine_gran_step) 671*dd11376bSBart Van Assche ufshcd_dme_set(hba, 672*dd11376bSBart Van Assche UIC_ARG_MIB_SEL(RX_ADV_GRANULARITY_CAP, 673*dd11376bSBart Van Assche i), RX_ADV_FINE_GRAN_STEP( 674*dd11376bSBart Van Assche attr->rx_adv_fine_gran_step)); 675*dd11376bSBart Van Assche 676*dd11376bSBart Van Assche if (attr->rx_adv_min_actv_time_cap) 677*dd11376bSBart Van Assche ufshcd_dme_set(hba, 678*dd11376bSBart Van Assche UIC_ARG_MIB_SEL( 679*dd11376bSBart Van Assche RX_ADV_MIN_ACTIVATETIME_CAP, i), 680*dd11376bSBart Van Assche attr->rx_adv_min_actv_time_cap); 681*dd11376bSBart Van Assche 682*dd11376bSBart Van Assche if (attr->rx_adv_hibern8_time_cap) 683*dd11376bSBart Van Assche ufshcd_dme_set(hba, 684*dd11376bSBart Van Assche UIC_ARG_MIB_SEL(RX_ADV_HIBERN8TIME_CAP, 685*dd11376bSBart Van Assche i), 686*dd11376bSBart Van Assche attr->rx_adv_hibern8_time_cap); 687*dd11376bSBart Van Assche } 688*dd11376bSBart Van Assche } 689*dd11376bSBart Van Assche 690*dd11376bSBart Van Assche exynos_ufs_disable_ov_tm(hba); 691*dd11376bSBart Van Assche } 692*dd11376bSBart Van Assche 693*dd11376bSBart Van Assche static void exynos_ufs_establish_connt(struct exynos_ufs *ufs) 694*dd11376bSBart Van Assche { 695*dd11376bSBart Van Assche struct ufs_hba *hba = ufs->hba; 696*dd11376bSBart Van Assche enum { 697*dd11376bSBart Van Assche DEV_ID = 0x00, 698*dd11376bSBart Van Assche PEER_DEV_ID = 0x01, 699*dd11376bSBart Van Assche PEER_CPORT_ID = 0x00, 700*dd11376bSBart Van Assche TRAFFIC_CLASS = 0x00, 701*dd11376bSBart Van Assche }; 702*dd11376bSBart Van Assche 703*dd11376bSBart Van Assche /* allow cport attributes to be set */ 704*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB(T_CONNECTIONSTATE), CPORT_IDLE); 705*dd11376bSBart Van Assche 706*dd11376bSBart Van Assche /* local unipro attributes */ 707*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB(N_DEVICEID), DEV_ID); 708*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB(N_DEVICEID_VALID), true); 709*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB(T_PEERDEVICEID), PEER_DEV_ID); 710*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB(T_PEERCPORTID), PEER_CPORT_ID); 711*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB(T_CPORTFLAGS), CPORT_DEF_FLAGS); 712*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB(T_TRAFFICCLASS), TRAFFIC_CLASS); 713*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB(T_CONNECTIONSTATE), CPORT_CONNECTED); 714*dd11376bSBart Van Assche } 715*dd11376bSBart Van Assche 716*dd11376bSBart Van Assche static void exynos_ufs_config_smu(struct exynos_ufs *ufs) 717*dd11376bSBart Van Assche { 718*dd11376bSBart Van Assche u32 reg, val; 719*dd11376bSBart Van Assche 720*dd11376bSBart Van Assche exynos_ufs_disable_auto_ctrl_hcc_save(ufs, &val); 721*dd11376bSBart Van Assche 722*dd11376bSBart Van Assche /* make encryption disabled by default */ 723*dd11376bSBart Van Assche reg = ufsp_readl(ufs, UFSPRSECURITY); 724*dd11376bSBart Van Assche ufsp_writel(ufs, reg | NSSMU, UFSPRSECURITY); 725*dd11376bSBart Van Assche ufsp_writel(ufs, 0x0, UFSPSBEGIN0); 726*dd11376bSBart Van Assche ufsp_writel(ufs, 0xffffffff, UFSPSEND0); 727*dd11376bSBart Van Assche ufsp_writel(ufs, 0xff, UFSPSLUN0); 728*dd11376bSBart Van Assche ufsp_writel(ufs, 0xf1, UFSPSCTRL0); 729*dd11376bSBart Van Assche 730*dd11376bSBart Van Assche exynos_ufs_auto_ctrl_hcc_restore(ufs, &val); 731*dd11376bSBart Van Assche } 732*dd11376bSBart Van Assche 733*dd11376bSBart Van Assche static void exynos_ufs_config_sync_pattern_mask(struct exynos_ufs *ufs, 734*dd11376bSBart Van Assche struct ufs_pa_layer_attr *pwr) 735*dd11376bSBart Van Assche { 736*dd11376bSBart Van Assche struct ufs_hba *hba = ufs->hba; 737*dd11376bSBart Van Assche u8 g = max_t(u32, pwr->gear_rx, pwr->gear_tx); 738*dd11376bSBart Van Assche u32 mask, sync_len; 739*dd11376bSBart Van Assche enum { 740*dd11376bSBart Van Assche SYNC_LEN_G1 = 80 * 1000, /* 80us */ 741*dd11376bSBart Van Assche SYNC_LEN_G2 = 40 * 1000, /* 44us */ 742*dd11376bSBart Van Assche SYNC_LEN_G3 = 20 * 1000, /* 20us */ 743*dd11376bSBart Van Assche }; 744*dd11376bSBart Van Assche int i; 745*dd11376bSBart Van Assche 746*dd11376bSBart Van Assche if (g == 1) 747*dd11376bSBart Van Assche sync_len = SYNC_LEN_G1; 748*dd11376bSBart Van Assche else if (g == 2) 749*dd11376bSBart Van Assche sync_len = SYNC_LEN_G2; 750*dd11376bSBart Van Assche else if (g == 3) 751*dd11376bSBart Van Assche sync_len = SYNC_LEN_G3; 752*dd11376bSBart Van Assche else 753*dd11376bSBart Van Assche return; 754*dd11376bSBart Van Assche 755*dd11376bSBart Van Assche mask = exynos_ufs_calc_time_cntr(ufs, sync_len); 756*dd11376bSBart Van Assche mask = (mask >> 8) & 0xff; 757*dd11376bSBart Van Assche 758*dd11376bSBart Van Assche exynos_ufs_enable_ov_tm(hba); 759*dd11376bSBart Van Assche 760*dd11376bSBart Van Assche for_each_ufs_rx_lane(ufs, i) 761*dd11376bSBart Van Assche ufshcd_dme_set(hba, 762*dd11376bSBart Van Assche UIC_ARG_MIB_SEL(RX_SYNC_MASK_LENGTH, i), mask); 763*dd11376bSBart Van Assche 764*dd11376bSBart Van Assche exynos_ufs_disable_ov_tm(hba); 765*dd11376bSBart Van Assche } 766*dd11376bSBart Van Assche 767*dd11376bSBart Van Assche static int exynos_ufs_pre_pwr_mode(struct ufs_hba *hba, 768*dd11376bSBart Van Assche struct ufs_pa_layer_attr *dev_max_params, 769*dd11376bSBart Van Assche struct ufs_pa_layer_attr *dev_req_params) 770*dd11376bSBart Van Assche { 771*dd11376bSBart Van Assche struct exynos_ufs *ufs = ufshcd_get_variant(hba); 772*dd11376bSBart Van Assche struct phy *generic_phy = ufs->phy; 773*dd11376bSBart Van Assche struct ufs_dev_params ufs_exynos_cap; 774*dd11376bSBart Van Assche int ret; 775*dd11376bSBart Van Assche 776*dd11376bSBart Van Assche if (!dev_req_params) { 777*dd11376bSBart Van Assche pr_err("%s: incoming dev_req_params is NULL\n", __func__); 778*dd11376bSBart Van Assche ret = -EINVAL; 779*dd11376bSBart Van Assche goto out; 780*dd11376bSBart Van Assche } 781*dd11376bSBart Van Assche 782*dd11376bSBart Van Assche ufshcd_init_pwr_dev_param(&ufs_exynos_cap); 783*dd11376bSBart Van Assche 784*dd11376bSBart Van Assche ret = ufshcd_get_pwr_dev_param(&ufs_exynos_cap, 785*dd11376bSBart Van Assche dev_max_params, dev_req_params); 786*dd11376bSBart Van Assche if (ret) { 787*dd11376bSBart Van Assche pr_err("%s: failed to determine capabilities\n", __func__); 788*dd11376bSBart Van Assche goto out; 789*dd11376bSBart Van Assche } 790*dd11376bSBart Van Assche 791*dd11376bSBart Van Assche if (ufs->drv_data->pre_pwr_change) 792*dd11376bSBart Van Assche ufs->drv_data->pre_pwr_change(ufs, dev_req_params); 793*dd11376bSBart Van Assche 794*dd11376bSBart Van Assche if (ufshcd_is_hs_mode(dev_req_params)) { 795*dd11376bSBart Van Assche exynos_ufs_config_sync_pattern_mask(ufs, dev_req_params); 796*dd11376bSBart Van Assche 797*dd11376bSBart Van Assche switch (dev_req_params->hs_rate) { 798*dd11376bSBart Van Assche case PA_HS_MODE_A: 799*dd11376bSBart Van Assche case PA_HS_MODE_B: 800*dd11376bSBart Van Assche phy_calibrate(generic_phy); 801*dd11376bSBart Van Assche break; 802*dd11376bSBart Van Assche } 803*dd11376bSBart Van Assche } 804*dd11376bSBart Van Assche 805*dd11376bSBart Van Assche /* setting for three timeout values for traffic class #0 */ 806*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB(DL_FC0PROTTIMEOUTVAL), 8064); 807*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB(DL_TC0REPLAYTIMEOUTVAL), 28224); 808*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB(DL_AFC0REQTIMEOUTVAL), 20160); 809*dd11376bSBart Van Assche 810*dd11376bSBart Van Assche return 0; 811*dd11376bSBart Van Assche out: 812*dd11376bSBart Van Assche return ret; 813*dd11376bSBart Van Assche } 814*dd11376bSBart Van Assche 815*dd11376bSBart Van Assche #define PWR_MODE_STR_LEN 64 816*dd11376bSBart Van Assche static int exynos_ufs_post_pwr_mode(struct ufs_hba *hba, 817*dd11376bSBart Van Assche struct ufs_pa_layer_attr *pwr_req) 818*dd11376bSBart Van Assche { 819*dd11376bSBart Van Assche struct exynos_ufs *ufs = ufshcd_get_variant(hba); 820*dd11376bSBart Van Assche struct phy *generic_phy = ufs->phy; 821*dd11376bSBart Van Assche int gear = max_t(u32, pwr_req->gear_rx, pwr_req->gear_tx); 822*dd11376bSBart Van Assche int lanes = max_t(u32, pwr_req->lane_rx, pwr_req->lane_tx); 823*dd11376bSBart Van Assche char pwr_str[PWR_MODE_STR_LEN] = ""; 824*dd11376bSBart Van Assche 825*dd11376bSBart Van Assche /* let default be PWM Gear 1, Lane 1 */ 826*dd11376bSBart Van Assche if (!gear) 827*dd11376bSBart Van Assche gear = 1; 828*dd11376bSBart Van Assche 829*dd11376bSBart Van Assche if (!lanes) 830*dd11376bSBart Van Assche lanes = 1; 831*dd11376bSBart Van Assche 832*dd11376bSBart Van Assche if (ufs->drv_data->post_pwr_change) 833*dd11376bSBart Van Assche ufs->drv_data->post_pwr_change(ufs, pwr_req); 834*dd11376bSBart Van Assche 835*dd11376bSBart Van Assche if ((ufshcd_is_hs_mode(pwr_req))) { 836*dd11376bSBart Van Assche switch (pwr_req->hs_rate) { 837*dd11376bSBart Van Assche case PA_HS_MODE_A: 838*dd11376bSBart Van Assche case PA_HS_MODE_B: 839*dd11376bSBart Van Assche phy_calibrate(generic_phy); 840*dd11376bSBart Van Assche break; 841*dd11376bSBart Van Assche } 842*dd11376bSBart Van Assche 843*dd11376bSBart Van Assche snprintf(pwr_str, PWR_MODE_STR_LEN, "%s series_%s G_%d L_%d", 844*dd11376bSBart Van Assche "FAST", pwr_req->hs_rate == PA_HS_MODE_A ? "A" : "B", 845*dd11376bSBart Van Assche gear, lanes); 846*dd11376bSBart Van Assche } else { 847*dd11376bSBart Van Assche snprintf(pwr_str, PWR_MODE_STR_LEN, "%s G_%d L_%d", 848*dd11376bSBart Van Assche "SLOW", gear, lanes); 849*dd11376bSBart Van Assche } 850*dd11376bSBart Van Assche 851*dd11376bSBart Van Assche dev_info(hba->dev, "Power mode changed to : %s\n", pwr_str); 852*dd11376bSBart Van Assche 853*dd11376bSBart Van Assche return 0; 854*dd11376bSBart Van Assche } 855*dd11376bSBart Van Assche 856*dd11376bSBart Van Assche static void exynos_ufs_specify_nexus_t_xfer_req(struct ufs_hba *hba, 857*dd11376bSBart Van Assche int tag, bool is_scsi_cmd) 858*dd11376bSBart Van Assche { 859*dd11376bSBart Van Assche struct exynos_ufs *ufs = ufshcd_get_variant(hba); 860*dd11376bSBart Van Assche u32 type; 861*dd11376bSBart Van Assche 862*dd11376bSBart Van Assche type = hci_readl(ufs, HCI_UTRL_NEXUS_TYPE); 863*dd11376bSBart Van Assche 864*dd11376bSBart Van Assche if (is_scsi_cmd) 865*dd11376bSBart Van Assche hci_writel(ufs, type | (1 << tag), HCI_UTRL_NEXUS_TYPE); 866*dd11376bSBart Van Assche else 867*dd11376bSBart Van Assche hci_writel(ufs, type & ~(1 << tag), HCI_UTRL_NEXUS_TYPE); 868*dd11376bSBart Van Assche } 869*dd11376bSBart Van Assche 870*dd11376bSBart Van Assche static void exynos_ufs_specify_nexus_t_tm_req(struct ufs_hba *hba, 871*dd11376bSBart Van Assche int tag, u8 func) 872*dd11376bSBart Van Assche { 873*dd11376bSBart Van Assche struct exynos_ufs *ufs = ufshcd_get_variant(hba); 874*dd11376bSBart Van Assche u32 type; 875*dd11376bSBart Van Assche 876*dd11376bSBart Van Assche type = hci_readl(ufs, HCI_UTMRL_NEXUS_TYPE); 877*dd11376bSBart Van Assche 878*dd11376bSBart Van Assche switch (func) { 879*dd11376bSBart Van Assche case UFS_ABORT_TASK: 880*dd11376bSBart Van Assche case UFS_QUERY_TASK: 881*dd11376bSBart Van Assche hci_writel(ufs, type | (1 << tag), HCI_UTMRL_NEXUS_TYPE); 882*dd11376bSBart Van Assche break; 883*dd11376bSBart Van Assche case UFS_ABORT_TASK_SET: 884*dd11376bSBart Van Assche case UFS_CLEAR_TASK_SET: 885*dd11376bSBart Van Assche case UFS_LOGICAL_RESET: 886*dd11376bSBart Van Assche case UFS_QUERY_TASK_SET: 887*dd11376bSBart Van Assche hci_writel(ufs, type & ~(1 << tag), HCI_UTMRL_NEXUS_TYPE); 888*dd11376bSBart Van Assche break; 889*dd11376bSBart Van Assche } 890*dd11376bSBart Van Assche } 891*dd11376bSBart Van Assche 892*dd11376bSBart Van Assche static int exynos_ufs_phy_init(struct exynos_ufs *ufs) 893*dd11376bSBart Van Assche { 894*dd11376bSBart Van Assche struct ufs_hba *hba = ufs->hba; 895*dd11376bSBart Van Assche struct phy *generic_phy = ufs->phy; 896*dd11376bSBart Van Assche int ret = 0; 897*dd11376bSBart Van Assche 898*dd11376bSBart Van Assche if (ufs->avail_ln_rx == 0 || ufs->avail_ln_tx == 0) { 899*dd11376bSBart Van Assche ufshcd_dme_get(hba, UIC_ARG_MIB(PA_AVAILRXDATALANES), 900*dd11376bSBart Van Assche &ufs->avail_ln_rx); 901*dd11376bSBart Van Assche ufshcd_dme_get(hba, UIC_ARG_MIB(PA_AVAILTXDATALANES), 902*dd11376bSBart Van Assche &ufs->avail_ln_tx); 903*dd11376bSBart Van Assche WARN(ufs->avail_ln_rx != ufs->avail_ln_tx, 904*dd11376bSBart Van Assche "available data lane is not equal(rx:%d, tx:%d)\n", 905*dd11376bSBart Van Assche ufs->avail_ln_rx, ufs->avail_ln_tx); 906*dd11376bSBart Van Assche } 907*dd11376bSBart Van Assche 908*dd11376bSBart Van Assche phy_set_bus_width(generic_phy, ufs->avail_ln_rx); 909*dd11376bSBart Van Assche ret = phy_init(generic_phy); 910*dd11376bSBart Van Assche if (ret) { 911*dd11376bSBart Van Assche dev_err(hba->dev, "%s: phy init failed, ret = %d\n", 912*dd11376bSBart Van Assche __func__, ret); 913*dd11376bSBart Van Assche goto out_exit_phy; 914*dd11376bSBart Van Assche } 915*dd11376bSBart Van Assche 916*dd11376bSBart Van Assche return 0; 917*dd11376bSBart Van Assche 918*dd11376bSBart Van Assche out_exit_phy: 919*dd11376bSBart Van Assche phy_exit(generic_phy); 920*dd11376bSBart Van Assche 921*dd11376bSBart Van Assche return ret; 922*dd11376bSBart Van Assche } 923*dd11376bSBart Van Assche 924*dd11376bSBart Van Assche static void exynos_ufs_config_unipro(struct exynos_ufs *ufs) 925*dd11376bSBart Van Assche { 926*dd11376bSBart Van Assche struct ufs_hba *hba = ufs->hba; 927*dd11376bSBart Van Assche 928*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_CLK_PERIOD), 929*dd11376bSBart Van Assche DIV_ROUND_UP(NSEC_PER_SEC, ufs->mclk_rate)); 930*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TXTRAILINGCLOCKS), 931*dd11376bSBart Van Assche ufs->drv_data->uic_attr->tx_trailingclks); 932*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_OPTION_SUITE), 933*dd11376bSBart Van Assche ufs->drv_data->uic_attr->pa_dbg_option_suite); 934*dd11376bSBart Van Assche } 935*dd11376bSBart Van Assche 936*dd11376bSBart Van Assche static void exynos_ufs_config_intr(struct exynos_ufs *ufs, u32 errs, u8 index) 937*dd11376bSBart Van Assche { 938*dd11376bSBart Van Assche switch (index) { 939*dd11376bSBart Van Assche case UNIPRO_L1_5: 940*dd11376bSBart Van Assche hci_writel(ufs, DFES_ERR_EN | errs, HCI_ERR_EN_PA_LAYER); 941*dd11376bSBart Van Assche break; 942*dd11376bSBart Van Assche case UNIPRO_L2: 943*dd11376bSBart Van Assche hci_writel(ufs, DFES_ERR_EN | errs, HCI_ERR_EN_DL_LAYER); 944*dd11376bSBart Van Assche break; 945*dd11376bSBart Van Assche case UNIPRO_L3: 946*dd11376bSBart Van Assche hci_writel(ufs, DFES_ERR_EN | errs, HCI_ERR_EN_N_LAYER); 947*dd11376bSBart Van Assche break; 948*dd11376bSBart Van Assche case UNIPRO_L4: 949*dd11376bSBart Van Assche hci_writel(ufs, DFES_ERR_EN | errs, HCI_ERR_EN_T_LAYER); 950*dd11376bSBart Van Assche break; 951*dd11376bSBart Van Assche case UNIPRO_DME: 952*dd11376bSBart Van Assche hci_writel(ufs, DFES_ERR_EN | errs, HCI_ERR_EN_DME_LAYER); 953*dd11376bSBart Van Assche break; 954*dd11376bSBart Van Assche } 955*dd11376bSBart Van Assche } 956*dd11376bSBart Van Assche 957*dd11376bSBart Van Assche static int exynos_ufs_setup_clocks(struct ufs_hba *hba, bool on, 958*dd11376bSBart Van Assche enum ufs_notify_change_status status) 959*dd11376bSBart Van Assche { 960*dd11376bSBart Van Assche struct exynos_ufs *ufs = ufshcd_get_variant(hba); 961*dd11376bSBart Van Assche 962*dd11376bSBart Van Assche if (!ufs) 963*dd11376bSBart Van Assche return 0; 964*dd11376bSBart Van Assche 965*dd11376bSBart Van Assche if (on && status == PRE_CHANGE) { 966*dd11376bSBart Van Assche if (ufs->opts & EXYNOS_UFS_OPT_BROKEN_AUTO_CLK_CTRL) 967*dd11376bSBart Van Assche exynos_ufs_disable_auto_ctrl_hcc(ufs); 968*dd11376bSBart Van Assche exynos_ufs_ungate_clks(ufs); 969*dd11376bSBart Van Assche } else if (!on && status == POST_CHANGE) { 970*dd11376bSBart Van Assche exynos_ufs_gate_clks(ufs); 971*dd11376bSBart Van Assche if (ufs->opts & EXYNOS_UFS_OPT_BROKEN_AUTO_CLK_CTRL) 972*dd11376bSBart Van Assche exynos_ufs_enable_auto_ctrl_hcc(ufs); 973*dd11376bSBart Van Assche } 974*dd11376bSBart Van Assche 975*dd11376bSBart Van Assche return 0; 976*dd11376bSBart Van Assche } 977*dd11376bSBart Van Assche 978*dd11376bSBart Van Assche static int exynos_ufs_pre_link(struct ufs_hba *hba) 979*dd11376bSBart Van Assche { 980*dd11376bSBart Van Assche struct exynos_ufs *ufs = ufshcd_get_variant(hba); 981*dd11376bSBart Van Assche 982*dd11376bSBart Van Assche /* hci */ 983*dd11376bSBart Van Assche exynos_ufs_config_intr(ufs, DFES_DEF_L2_ERRS, UNIPRO_L2); 984*dd11376bSBart Van Assche exynos_ufs_config_intr(ufs, DFES_DEF_L3_ERRS, UNIPRO_L3); 985*dd11376bSBart Van Assche exynos_ufs_config_intr(ufs, DFES_DEF_L4_ERRS, UNIPRO_L4); 986*dd11376bSBart Van Assche exynos_ufs_set_unipro_pclk_div(ufs); 987*dd11376bSBart Van Assche 988*dd11376bSBart Van Assche /* unipro */ 989*dd11376bSBart Van Assche exynos_ufs_config_unipro(ufs); 990*dd11376bSBart Van Assche 991*dd11376bSBart Van Assche /* m-phy */ 992*dd11376bSBart Van Assche exynos_ufs_phy_init(ufs); 993*dd11376bSBart Van Assche if (!(ufs->opts & EXYNOS_UFS_OPT_SKIP_CONFIG_PHY_ATTR)) { 994*dd11376bSBart Van Assche exynos_ufs_config_phy_time_attr(ufs); 995*dd11376bSBart Van Assche exynos_ufs_config_phy_cap_attr(ufs); 996*dd11376bSBart Van Assche } 997*dd11376bSBart Van Assche 998*dd11376bSBart Van Assche exynos_ufs_setup_clocks(hba, true, PRE_CHANGE); 999*dd11376bSBart Van Assche 1000*dd11376bSBart Van Assche if (ufs->drv_data->pre_link) 1001*dd11376bSBart Van Assche ufs->drv_data->pre_link(ufs); 1002*dd11376bSBart Van Assche 1003*dd11376bSBart Van Assche return 0; 1004*dd11376bSBart Van Assche } 1005*dd11376bSBart Van Assche 1006*dd11376bSBart Van Assche static void exynos_ufs_fit_aggr_timeout(struct exynos_ufs *ufs) 1007*dd11376bSBart Van Assche { 1008*dd11376bSBart Van Assche u32 val; 1009*dd11376bSBart Van Assche 1010*dd11376bSBart Van Assche val = exynos_ufs_calc_time_cntr(ufs, IATOVAL_NSEC / CNTR_DIV_VAL); 1011*dd11376bSBart Van Assche hci_writel(ufs, val & CNT_VAL_1US_MASK, HCI_1US_TO_CNT_VAL); 1012*dd11376bSBart Van Assche } 1013*dd11376bSBart Van Assche 1014*dd11376bSBart Van Assche static int exynos_ufs_post_link(struct ufs_hba *hba) 1015*dd11376bSBart Van Assche { 1016*dd11376bSBart Van Assche struct exynos_ufs *ufs = ufshcd_get_variant(hba); 1017*dd11376bSBart Van Assche struct phy *generic_phy = ufs->phy; 1018*dd11376bSBart Van Assche struct exynos_ufs_uic_attr *attr = ufs->drv_data->uic_attr; 1019*dd11376bSBart Van Assche 1020*dd11376bSBart Van Assche exynos_ufs_establish_connt(ufs); 1021*dd11376bSBart Van Assche exynos_ufs_fit_aggr_timeout(ufs); 1022*dd11376bSBart Van Assche 1023*dd11376bSBart Van Assche hci_writel(ufs, 0xa, HCI_DATA_REORDER); 1024*dd11376bSBart Van Assche hci_writel(ufs, PRDT_SET_SIZE(12), HCI_TXPRDT_ENTRY_SIZE); 1025*dd11376bSBart Van Assche hci_writel(ufs, PRDT_SET_SIZE(12), HCI_RXPRDT_ENTRY_SIZE); 1026*dd11376bSBart Van Assche hci_writel(ufs, (1 << hba->nutrs) - 1, HCI_UTRL_NEXUS_TYPE); 1027*dd11376bSBart Van Assche hci_writel(ufs, (1 << hba->nutmrs) - 1, HCI_UTMRL_NEXUS_TYPE); 1028*dd11376bSBart Van Assche hci_writel(ufs, 0xf, HCI_AXIDMA_RWDATA_BURST_LEN); 1029*dd11376bSBart Van Assche 1030*dd11376bSBart Van Assche if (ufs->opts & EXYNOS_UFS_OPT_SKIP_CONNECTION_ESTAB) 1031*dd11376bSBart Van Assche ufshcd_dme_set(hba, 1032*dd11376bSBart Van Assche UIC_ARG_MIB(T_DBG_SKIP_INIT_HIBERN8_EXIT), true); 1033*dd11376bSBart Van Assche 1034*dd11376bSBart Van Assche if (attr->pa_granularity) { 1035*dd11376bSBart Van Assche exynos_ufs_enable_dbg_mode(hba); 1036*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB(PA_GRANULARITY), 1037*dd11376bSBart Van Assche attr->pa_granularity); 1038*dd11376bSBart Van Assche exynos_ufs_disable_dbg_mode(hba); 1039*dd11376bSBart Van Assche 1040*dd11376bSBart Van Assche if (attr->pa_tactivate) 1041*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TACTIVATE), 1042*dd11376bSBart Van Assche attr->pa_tactivate); 1043*dd11376bSBart Van Assche if (attr->pa_hibern8time && 1044*dd11376bSBart Van Assche !(ufs->opts & EXYNOS_UFS_OPT_USE_SW_HIBERN8_TIMER)) 1045*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB(PA_HIBERN8TIME), 1046*dd11376bSBart Van Assche attr->pa_hibern8time); 1047*dd11376bSBart Van Assche } 1048*dd11376bSBart Van Assche 1049*dd11376bSBart Van Assche if (ufs->opts & EXYNOS_UFS_OPT_USE_SW_HIBERN8_TIMER) { 1050*dd11376bSBart Van Assche if (!attr->pa_granularity) 1051*dd11376bSBart Van Assche ufshcd_dme_get(hba, UIC_ARG_MIB(PA_GRANULARITY), 1052*dd11376bSBart Van Assche &attr->pa_granularity); 1053*dd11376bSBart Van Assche if (!attr->pa_hibern8time) 1054*dd11376bSBart Van Assche ufshcd_dme_get(hba, UIC_ARG_MIB(PA_HIBERN8TIME), 1055*dd11376bSBart Van Assche &attr->pa_hibern8time); 1056*dd11376bSBart Van Assche /* 1057*dd11376bSBart Van Assche * not wait for HIBERN8 time to exit hibernation 1058*dd11376bSBart Van Assche */ 1059*dd11376bSBart Van Assche ufshcd_dme_set(hba, UIC_ARG_MIB(PA_HIBERN8TIME), 0); 1060*dd11376bSBart Van Assche 1061*dd11376bSBart Van Assche if (attr->pa_granularity < 1 || attr->pa_granularity > 6) { 1062*dd11376bSBart Van Assche /* Valid range for granularity: 1 ~ 6 */ 1063*dd11376bSBart Van Assche dev_warn(hba->dev, 1064*dd11376bSBart Van Assche "%s: pa_granularity %d is invalid, assuming backwards compatibility\n", 1065*dd11376bSBart Van Assche __func__, 1066*dd11376bSBart Van Assche attr->pa_granularity); 1067*dd11376bSBart Van Assche attr->pa_granularity = 6; 1068*dd11376bSBart Van Assche } 1069*dd11376bSBart Van Assche } 1070*dd11376bSBart Van Assche 1071*dd11376bSBart Van Assche phy_calibrate(generic_phy); 1072*dd11376bSBart Van Assche 1073*dd11376bSBart Van Assche if (ufs->drv_data->post_link) 1074*dd11376bSBart Van Assche ufs->drv_data->post_link(ufs); 1075*dd11376bSBart Van Assche 1076*dd11376bSBart Van Assche return 0; 1077*dd11376bSBart Van Assche } 1078*dd11376bSBart Van Assche 1079*dd11376bSBart Van Assche static int exynos_ufs_parse_dt(struct device *dev, struct exynos_ufs *ufs) 1080*dd11376bSBart Van Assche { 1081*dd11376bSBart Van Assche struct device_node *np = dev->of_node; 1082*dd11376bSBart Van Assche struct exynos_ufs_uic_attr *attr; 1083*dd11376bSBart Van Assche int ret = 0; 1084*dd11376bSBart Van Assche 1085*dd11376bSBart Van Assche ufs->drv_data = device_get_match_data(dev); 1086*dd11376bSBart Van Assche 1087*dd11376bSBart Van Assche if (ufs->drv_data && ufs->drv_data->uic_attr) { 1088*dd11376bSBart Van Assche attr = ufs->drv_data->uic_attr; 1089*dd11376bSBart Van Assche } else { 1090*dd11376bSBart Van Assche dev_err(dev, "failed to get uic attributes\n"); 1091*dd11376bSBart Van Assche ret = -EINVAL; 1092*dd11376bSBart Van Assche goto out; 1093*dd11376bSBart Van Assche } 1094*dd11376bSBart Van Assche 1095*dd11376bSBart Van Assche ufs->sysreg = syscon_regmap_lookup_by_phandle(np, "samsung,sysreg"); 1096*dd11376bSBart Van Assche if (IS_ERR(ufs->sysreg)) 1097*dd11376bSBart Van Assche ufs->sysreg = NULL; 1098*dd11376bSBart Van Assche else { 1099*dd11376bSBart Van Assche if (of_property_read_u32_index(np, "samsung,sysreg", 1, 1100*dd11376bSBart Van Assche &ufs->shareability_reg_offset)) { 1101*dd11376bSBart Van Assche dev_warn(dev, "can't get an offset from sysreg. Set to default value\n"); 1102*dd11376bSBart Van Assche ufs->shareability_reg_offset = UFS_SHAREABILITY_OFFSET; 1103*dd11376bSBart Van Assche } 1104*dd11376bSBart Van Assche } 1105*dd11376bSBart Van Assche 1106*dd11376bSBart Van Assche ufs->pclk_avail_min = PCLK_AVAIL_MIN; 1107*dd11376bSBart Van Assche ufs->pclk_avail_max = PCLK_AVAIL_MAX; 1108*dd11376bSBart Van Assche 1109*dd11376bSBart Van Assche attr->rx_adv_fine_gran_sup_en = RX_ADV_FINE_GRAN_SUP_EN; 1110*dd11376bSBart Van Assche attr->rx_adv_fine_gran_step = RX_ADV_FINE_GRAN_STEP_VAL; 1111*dd11376bSBart Van Assche attr->rx_adv_min_actv_time_cap = RX_ADV_MIN_ACTV_TIME_CAP; 1112*dd11376bSBart Van Assche attr->pa_granularity = PA_GRANULARITY_VAL; 1113*dd11376bSBart Van Assche attr->pa_tactivate = PA_TACTIVATE_VAL; 1114*dd11376bSBart Van Assche attr->pa_hibern8time = PA_HIBERN8TIME_VAL; 1115*dd11376bSBart Van Assche 1116*dd11376bSBart Van Assche out: 1117*dd11376bSBart Van Assche return ret; 1118*dd11376bSBart Van Assche } 1119*dd11376bSBart Van Assche 1120*dd11376bSBart Van Assche static inline void exynos_ufs_priv_init(struct ufs_hba *hba, 1121*dd11376bSBart Van Assche struct exynos_ufs *ufs) 1122*dd11376bSBart Van Assche { 1123*dd11376bSBart Van Assche ufs->hba = hba; 1124*dd11376bSBart Van Assche ufs->opts = ufs->drv_data->opts; 1125*dd11376bSBart Van Assche ufs->rx_sel_idx = PA_MAXDATALANES; 1126*dd11376bSBart Van Assche if (ufs->opts & EXYNOS_UFS_OPT_BROKEN_RX_SEL_IDX) 1127*dd11376bSBart Van Assche ufs->rx_sel_idx = 0; 1128*dd11376bSBart Van Assche hba->priv = (void *)ufs; 1129*dd11376bSBart Van Assche hba->quirks = ufs->drv_data->quirks; 1130*dd11376bSBart Van Assche } 1131*dd11376bSBart Van Assche 1132*dd11376bSBart Van Assche static int exynos_ufs_init(struct ufs_hba *hba) 1133*dd11376bSBart Van Assche { 1134*dd11376bSBart Van Assche struct device *dev = hba->dev; 1135*dd11376bSBart Van Assche struct platform_device *pdev = to_platform_device(dev); 1136*dd11376bSBart Van Assche struct exynos_ufs *ufs; 1137*dd11376bSBart Van Assche int ret; 1138*dd11376bSBart Van Assche 1139*dd11376bSBart Van Assche ufs = devm_kzalloc(dev, sizeof(*ufs), GFP_KERNEL); 1140*dd11376bSBart Van Assche if (!ufs) 1141*dd11376bSBart Van Assche return -ENOMEM; 1142*dd11376bSBart Van Assche 1143*dd11376bSBart Van Assche /* exynos-specific hci */ 1144*dd11376bSBart Van Assche ufs->reg_hci = devm_platform_ioremap_resource_byname(pdev, "vs_hci"); 1145*dd11376bSBart Van Assche if (IS_ERR(ufs->reg_hci)) { 1146*dd11376bSBart Van Assche dev_err(dev, "cannot ioremap for hci vendor register\n"); 1147*dd11376bSBart Van Assche return PTR_ERR(ufs->reg_hci); 1148*dd11376bSBart Van Assche } 1149*dd11376bSBart Van Assche 1150*dd11376bSBart Van Assche /* unipro */ 1151*dd11376bSBart Van Assche ufs->reg_unipro = devm_platform_ioremap_resource_byname(pdev, "unipro"); 1152*dd11376bSBart Van Assche if (IS_ERR(ufs->reg_unipro)) { 1153*dd11376bSBart Van Assche dev_err(dev, "cannot ioremap for unipro register\n"); 1154*dd11376bSBart Van Assche return PTR_ERR(ufs->reg_unipro); 1155*dd11376bSBart Van Assche } 1156*dd11376bSBart Van Assche 1157*dd11376bSBart Van Assche /* ufs protector */ 1158*dd11376bSBart Van Assche ufs->reg_ufsp = devm_platform_ioremap_resource_byname(pdev, "ufsp"); 1159*dd11376bSBart Van Assche if (IS_ERR(ufs->reg_ufsp)) { 1160*dd11376bSBart Van Assche dev_err(dev, "cannot ioremap for ufs protector register\n"); 1161*dd11376bSBart Van Assche return PTR_ERR(ufs->reg_ufsp); 1162*dd11376bSBart Van Assche } 1163*dd11376bSBart Van Assche 1164*dd11376bSBart Van Assche ret = exynos_ufs_parse_dt(dev, ufs); 1165*dd11376bSBart Van Assche if (ret) { 1166*dd11376bSBart Van Assche dev_err(dev, "failed to get dt info.\n"); 1167*dd11376bSBart Van Assche goto out; 1168*dd11376bSBart Van Assche } 1169*dd11376bSBart Van Assche 1170*dd11376bSBart Van Assche ufs->phy = devm_phy_get(dev, "ufs-phy"); 1171*dd11376bSBart Van Assche if (IS_ERR(ufs->phy)) { 1172*dd11376bSBart Van Assche ret = PTR_ERR(ufs->phy); 1173*dd11376bSBart Van Assche dev_err(dev, "failed to get ufs-phy\n"); 1174*dd11376bSBart Van Assche goto out; 1175*dd11376bSBart Van Assche } 1176*dd11376bSBart Van Assche 1177*dd11376bSBart Van Assche ret = phy_power_on(ufs->phy); 1178*dd11376bSBart Van Assche if (ret) 1179*dd11376bSBart Van Assche goto phy_off; 1180*dd11376bSBart Van Assche 1181*dd11376bSBart Van Assche exynos_ufs_priv_init(hba, ufs); 1182*dd11376bSBart Van Assche 1183*dd11376bSBart Van Assche if (ufs->drv_data->drv_init) { 1184*dd11376bSBart Van Assche ret = ufs->drv_data->drv_init(dev, ufs); 1185*dd11376bSBart Van Assche if (ret) { 1186*dd11376bSBart Van Assche dev_err(dev, "failed to init drv-data\n"); 1187*dd11376bSBart Van Assche goto out; 1188*dd11376bSBart Van Assche } 1189*dd11376bSBart Van Assche } 1190*dd11376bSBart Van Assche 1191*dd11376bSBart Van Assche ret = exynos_ufs_get_clk_info(ufs); 1192*dd11376bSBart Van Assche if (ret) 1193*dd11376bSBart Van Assche goto out; 1194*dd11376bSBart Van Assche exynos_ufs_specify_phy_time_attr(ufs); 1195*dd11376bSBart Van Assche exynos_ufs_config_smu(ufs); 1196*dd11376bSBart Van Assche return 0; 1197*dd11376bSBart Van Assche 1198*dd11376bSBart Van Assche phy_off: 1199*dd11376bSBart Van Assche phy_power_off(ufs->phy); 1200*dd11376bSBart Van Assche out: 1201*dd11376bSBart Van Assche hba->priv = NULL; 1202*dd11376bSBart Van Assche return ret; 1203*dd11376bSBart Van Assche } 1204*dd11376bSBart Van Assche 1205*dd11376bSBart Van Assche static int exynos_ufs_host_reset(struct ufs_hba *hba) 1206*dd11376bSBart Van Assche { 1207*dd11376bSBart Van Assche struct exynos_ufs *ufs = ufshcd_get_variant(hba); 1208*dd11376bSBart Van Assche unsigned long timeout = jiffies + msecs_to_jiffies(1); 1209*dd11376bSBart Van Assche u32 val; 1210*dd11376bSBart Van Assche int ret = 0; 1211*dd11376bSBart Van Assche 1212*dd11376bSBart Van Assche exynos_ufs_disable_auto_ctrl_hcc_save(ufs, &val); 1213*dd11376bSBart Van Assche 1214*dd11376bSBart Van Assche hci_writel(ufs, UFS_SW_RST_MASK, HCI_SW_RST); 1215*dd11376bSBart Van Assche 1216*dd11376bSBart Van Assche do { 1217*dd11376bSBart Van Assche if (!(hci_readl(ufs, HCI_SW_RST) & UFS_SW_RST_MASK)) 1218*dd11376bSBart Van Assche goto out; 1219*dd11376bSBart Van Assche } while (time_before(jiffies, timeout)); 1220*dd11376bSBart Van Assche 1221*dd11376bSBart Van Assche dev_err(hba->dev, "timeout host sw-reset\n"); 1222*dd11376bSBart Van Assche ret = -ETIMEDOUT; 1223*dd11376bSBart Van Assche 1224*dd11376bSBart Van Assche out: 1225*dd11376bSBart Van Assche exynos_ufs_auto_ctrl_hcc_restore(ufs, &val); 1226*dd11376bSBart Van Assche return ret; 1227*dd11376bSBart Van Assche } 1228*dd11376bSBart Van Assche 1229*dd11376bSBart Van Assche static void exynos_ufs_dev_hw_reset(struct ufs_hba *hba) 1230*dd11376bSBart Van Assche { 1231*dd11376bSBart Van Assche struct exynos_ufs *ufs = ufshcd_get_variant(hba); 1232*dd11376bSBart Van Assche 1233*dd11376bSBart Van Assche hci_writel(ufs, 0 << 0, HCI_GPIO_OUT); 1234*dd11376bSBart Van Assche udelay(5); 1235*dd11376bSBart Van Assche hci_writel(ufs, 1 << 0, HCI_GPIO_OUT); 1236*dd11376bSBart Van Assche } 1237*dd11376bSBart Van Assche 1238*dd11376bSBart Van Assche static void exynos_ufs_pre_hibern8(struct ufs_hba *hba, u8 enter) 1239*dd11376bSBart Van Assche { 1240*dd11376bSBart Van Assche struct exynos_ufs *ufs = ufshcd_get_variant(hba); 1241*dd11376bSBart Van Assche struct exynos_ufs_uic_attr *attr = ufs->drv_data->uic_attr; 1242*dd11376bSBart Van Assche 1243*dd11376bSBart Van Assche if (!enter) { 1244*dd11376bSBart Van Assche if (ufs->opts & EXYNOS_UFS_OPT_BROKEN_AUTO_CLK_CTRL) 1245*dd11376bSBart Van Assche exynos_ufs_disable_auto_ctrl_hcc(ufs); 1246*dd11376bSBart Van Assche exynos_ufs_ungate_clks(ufs); 1247*dd11376bSBart Van Assche 1248*dd11376bSBart Van Assche if (ufs->opts & EXYNOS_UFS_OPT_USE_SW_HIBERN8_TIMER) { 1249*dd11376bSBart Van Assche static const unsigned int granularity_tbl[] = { 1250*dd11376bSBart Van Assche 1, 4, 8, 16, 32, 100 1251*dd11376bSBart Van Assche }; 1252*dd11376bSBart Van Assche int h8_time = attr->pa_hibern8time * 1253*dd11376bSBart Van Assche granularity_tbl[attr->pa_granularity - 1]; 1254*dd11376bSBart Van Assche unsigned long us; 1255*dd11376bSBart Van Assche s64 delta; 1256*dd11376bSBart Van Assche 1257*dd11376bSBart Van Assche do { 1258*dd11376bSBart Van Assche delta = h8_time - ktime_us_delta(ktime_get(), 1259*dd11376bSBart Van Assche ufs->entry_hibern8_t); 1260*dd11376bSBart Van Assche if (delta <= 0) 1261*dd11376bSBart Van Assche break; 1262*dd11376bSBart Van Assche 1263*dd11376bSBart Van Assche us = min_t(s64, delta, USEC_PER_MSEC); 1264*dd11376bSBart Van Assche if (us >= 10) 1265*dd11376bSBart Van Assche usleep_range(us, us + 10); 1266*dd11376bSBart Van Assche } while (1); 1267*dd11376bSBart Van Assche } 1268*dd11376bSBart Van Assche } 1269*dd11376bSBart Van Assche } 1270*dd11376bSBart Van Assche 1271*dd11376bSBart Van Assche static void exynos_ufs_post_hibern8(struct ufs_hba *hba, u8 enter) 1272*dd11376bSBart Van Assche { 1273*dd11376bSBart Van Assche struct exynos_ufs *ufs = ufshcd_get_variant(hba); 1274*dd11376bSBart Van Assche 1275*dd11376bSBart Van Assche if (!enter) { 1276*dd11376bSBart Van Assche u32 cur_mode = 0; 1277*dd11376bSBart Van Assche u32 pwrmode; 1278*dd11376bSBart Van Assche 1279*dd11376bSBart Van Assche if (ufshcd_is_hs_mode(&ufs->dev_req_params)) 1280*dd11376bSBart Van Assche pwrmode = FAST_MODE; 1281*dd11376bSBart Van Assche else 1282*dd11376bSBart Van Assche pwrmode = SLOW_MODE; 1283*dd11376bSBart Van Assche 1284*dd11376bSBart Van Assche ufshcd_dme_get(hba, UIC_ARG_MIB(PA_PWRMODE), &cur_mode); 1285*dd11376bSBart Van Assche if (cur_mode != (pwrmode << 4 | pwrmode)) { 1286*dd11376bSBart Van Assche dev_warn(hba->dev, "%s: power mode change\n", __func__); 1287*dd11376bSBart Van Assche hba->pwr_info.pwr_rx = (cur_mode >> 4) & 0xf; 1288*dd11376bSBart Van Assche hba->pwr_info.pwr_tx = cur_mode & 0xf; 1289*dd11376bSBart Van Assche ufshcd_config_pwr_mode(hba, &hba->max_pwr_info.info); 1290*dd11376bSBart Van Assche } 1291*dd11376bSBart Van Assche 1292*dd11376bSBart Van Assche if (!(ufs->opts & EXYNOS_UFS_OPT_SKIP_CONNECTION_ESTAB)) 1293*dd11376bSBart Van Assche exynos_ufs_establish_connt(ufs); 1294*dd11376bSBart Van Assche } else { 1295*dd11376bSBart Van Assche ufs->entry_hibern8_t = ktime_get(); 1296*dd11376bSBart Van Assche exynos_ufs_gate_clks(ufs); 1297*dd11376bSBart Van Assche if (ufs->opts & EXYNOS_UFS_OPT_BROKEN_AUTO_CLK_CTRL) 1298*dd11376bSBart Van Assche exynos_ufs_enable_auto_ctrl_hcc(ufs); 1299*dd11376bSBart Van Assche } 1300*dd11376bSBart Van Assche } 1301*dd11376bSBart Van Assche 1302*dd11376bSBart Van Assche static int exynos_ufs_hce_enable_notify(struct ufs_hba *hba, 1303*dd11376bSBart Van Assche enum ufs_notify_change_status status) 1304*dd11376bSBart Van Assche { 1305*dd11376bSBart Van Assche struct exynos_ufs *ufs = ufshcd_get_variant(hba); 1306*dd11376bSBart Van Assche int ret = 0; 1307*dd11376bSBart Van Assche 1308*dd11376bSBart Van Assche switch (status) { 1309*dd11376bSBart Van Assche case PRE_CHANGE: 1310*dd11376bSBart Van Assche if (ufs->drv_data->pre_hce_enable) { 1311*dd11376bSBart Van Assche ret = ufs->drv_data->pre_hce_enable(ufs); 1312*dd11376bSBart Van Assche if (ret) 1313*dd11376bSBart Van Assche return ret; 1314*dd11376bSBart Van Assche } 1315*dd11376bSBart Van Assche 1316*dd11376bSBart Van Assche ret = exynos_ufs_host_reset(hba); 1317*dd11376bSBart Van Assche if (ret) 1318*dd11376bSBart Van Assche return ret; 1319*dd11376bSBart Van Assche exynos_ufs_dev_hw_reset(hba); 1320*dd11376bSBart Van Assche break; 1321*dd11376bSBart Van Assche case POST_CHANGE: 1322*dd11376bSBart Van Assche exynos_ufs_calc_pwm_clk_div(ufs); 1323*dd11376bSBart Van Assche if (!(ufs->opts & EXYNOS_UFS_OPT_BROKEN_AUTO_CLK_CTRL)) 1324*dd11376bSBart Van Assche exynos_ufs_enable_auto_ctrl_hcc(ufs); 1325*dd11376bSBart Van Assche 1326*dd11376bSBart Van Assche if (ufs->drv_data->post_hce_enable) 1327*dd11376bSBart Van Assche ret = ufs->drv_data->post_hce_enable(ufs); 1328*dd11376bSBart Van Assche 1329*dd11376bSBart Van Assche break; 1330*dd11376bSBart Van Assche } 1331*dd11376bSBart Van Assche 1332*dd11376bSBart Van Assche return ret; 1333*dd11376bSBart Van Assche } 1334*dd11376bSBart Van Assche 1335*dd11376bSBart Van Assche static int exynos_ufs_link_startup_notify(struct ufs_hba *hba, 1336*dd11376bSBart Van Assche enum ufs_notify_change_status status) 1337*dd11376bSBart Van Assche { 1338*dd11376bSBart Van Assche int ret = 0; 1339*dd11376bSBart Van Assche 1340*dd11376bSBart Van Assche switch (status) { 1341*dd11376bSBart Van Assche case PRE_CHANGE: 1342*dd11376bSBart Van Assche ret = exynos_ufs_pre_link(hba); 1343*dd11376bSBart Van Assche break; 1344*dd11376bSBart Van Assche case POST_CHANGE: 1345*dd11376bSBart Van Assche ret = exynos_ufs_post_link(hba); 1346*dd11376bSBart Van Assche break; 1347*dd11376bSBart Van Assche } 1348*dd11376bSBart Van Assche 1349*dd11376bSBart Van Assche return ret; 1350*dd11376bSBart Van Assche } 1351*dd11376bSBart Van Assche 1352*dd11376bSBart Van Assche static int exynos_ufs_pwr_change_notify(struct ufs_hba *hba, 1353*dd11376bSBart Van Assche enum ufs_notify_change_status status, 1354*dd11376bSBart Van Assche struct ufs_pa_layer_attr *dev_max_params, 1355*dd11376bSBart Van Assche struct ufs_pa_layer_attr *dev_req_params) 1356*dd11376bSBart Van Assche { 1357*dd11376bSBart Van Assche int ret = 0; 1358*dd11376bSBart Van Assche 1359*dd11376bSBart Van Assche switch (status) { 1360*dd11376bSBart Van Assche case PRE_CHANGE: 1361*dd11376bSBart Van Assche ret = exynos_ufs_pre_pwr_mode(hba, dev_max_params, 1362*dd11376bSBart Van Assche dev_req_params); 1363*dd11376bSBart Van Assche break; 1364*dd11376bSBart Van Assche case POST_CHANGE: 1365*dd11376bSBart Van Assche ret = exynos_ufs_post_pwr_mode(hba, dev_req_params); 1366*dd11376bSBart Van Assche break; 1367*dd11376bSBart Van Assche } 1368*dd11376bSBart Van Assche 1369*dd11376bSBart Van Assche return ret; 1370*dd11376bSBart Van Assche } 1371*dd11376bSBart Van Assche 1372*dd11376bSBart Van Assche static void exynos_ufs_hibern8_notify(struct ufs_hba *hba, 1373*dd11376bSBart Van Assche enum uic_cmd_dme enter, 1374*dd11376bSBart Van Assche enum ufs_notify_change_status notify) 1375*dd11376bSBart Van Assche { 1376*dd11376bSBart Van Assche switch ((u8)notify) { 1377*dd11376bSBart Van Assche case PRE_CHANGE: 1378*dd11376bSBart Van Assche exynos_ufs_pre_hibern8(hba, enter); 1379*dd11376bSBart Van Assche break; 1380*dd11376bSBart Van Assche case POST_CHANGE: 1381*dd11376bSBart Van Assche exynos_ufs_post_hibern8(hba, enter); 1382*dd11376bSBart Van Assche break; 1383*dd11376bSBart Van Assche } 1384*dd11376bSBart Van Assche } 1385*dd11376bSBart Van Assche 1386*dd11376bSBart Van Assche static int exynos_ufs_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op, 1387*dd11376bSBart Van Assche enum ufs_notify_change_status status) 1388*dd11376bSBart Van Assche { 1389*dd11376bSBart Van Assche struct exynos_ufs *ufs = ufshcd_get_variant(hba); 1390*dd11376bSBart Van Assche 1391*dd11376bSBart Van Assche if (status == PRE_CHANGE) 1392*dd11376bSBart Van Assche return 0; 1393*dd11376bSBart Van Assche 1394*dd11376bSBart Van Assche if (!ufshcd_is_link_active(hba)) 1395*dd11376bSBart Van Assche phy_power_off(ufs->phy); 1396*dd11376bSBart Van Assche 1397*dd11376bSBart Van Assche return 0; 1398*dd11376bSBart Van Assche } 1399*dd11376bSBart Van Assche 1400*dd11376bSBart Van Assche static int exynos_ufs_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) 1401*dd11376bSBart Van Assche { 1402*dd11376bSBart Van Assche struct exynos_ufs *ufs = ufshcd_get_variant(hba); 1403*dd11376bSBart Van Assche 1404*dd11376bSBart Van Assche if (!ufshcd_is_link_active(hba)) 1405*dd11376bSBart Van Assche phy_power_on(ufs->phy); 1406*dd11376bSBart Van Assche 1407*dd11376bSBart Van Assche exynos_ufs_config_smu(ufs); 1408*dd11376bSBart Van Assche 1409*dd11376bSBart Van Assche return 0; 1410*dd11376bSBart Van Assche } 1411*dd11376bSBart Van Assche 1412*dd11376bSBart Van Assche static int exynosauto_ufs_vh_link_startup_notify(struct ufs_hba *hba, 1413*dd11376bSBart Van Assche enum ufs_notify_change_status status) 1414*dd11376bSBart Van Assche { 1415*dd11376bSBart Van Assche if (status == POST_CHANGE) { 1416*dd11376bSBart Van Assche ufshcd_set_link_active(hba); 1417*dd11376bSBart Van Assche ufshcd_set_ufs_dev_active(hba); 1418*dd11376bSBart Van Assche } 1419*dd11376bSBart Van Assche 1420*dd11376bSBart Van Assche return 0; 1421*dd11376bSBart Van Assche } 1422*dd11376bSBart Van Assche 1423*dd11376bSBart Van Assche static int exynosauto_ufs_vh_wait_ph_ready(struct ufs_hba *hba) 1424*dd11376bSBart Van Assche { 1425*dd11376bSBart Van Assche u32 mbox; 1426*dd11376bSBart Van Assche ktime_t start, stop; 1427*dd11376bSBart Van Assche 1428*dd11376bSBart Van Assche start = ktime_get(); 1429*dd11376bSBart Van Assche stop = ktime_add(start, ms_to_ktime(PH_READY_TIMEOUT_MS)); 1430*dd11376bSBart Van Assche 1431*dd11376bSBart Van Assche do { 1432*dd11376bSBart Van Assche mbox = ufshcd_readl(hba, PH2VH_MBOX); 1433*dd11376bSBart Van Assche /* TODO: Mailbox message protocols between the PH and VHs are 1434*dd11376bSBart Van Assche * not implemented yet. This will be supported later 1435*dd11376bSBart Van Assche */ 1436*dd11376bSBart Van Assche if ((mbox & MH_MSG_MASK) == MH_MSG_PH_READY) 1437*dd11376bSBart Van Assche return 0; 1438*dd11376bSBart Van Assche 1439*dd11376bSBart Van Assche usleep_range(40, 50); 1440*dd11376bSBart Van Assche } while (ktime_before(ktime_get(), stop)); 1441*dd11376bSBart Van Assche 1442*dd11376bSBart Van Assche return -ETIME; 1443*dd11376bSBart Van Assche } 1444*dd11376bSBart Van Assche 1445*dd11376bSBart Van Assche static int exynosauto_ufs_vh_init(struct ufs_hba *hba) 1446*dd11376bSBart Van Assche { 1447*dd11376bSBart Van Assche struct device *dev = hba->dev; 1448*dd11376bSBart Van Assche struct platform_device *pdev = to_platform_device(dev); 1449*dd11376bSBart Van Assche struct exynos_ufs *ufs; 1450*dd11376bSBart Van Assche int ret; 1451*dd11376bSBart Van Assche 1452*dd11376bSBart Van Assche ufs = devm_kzalloc(dev, sizeof(*ufs), GFP_KERNEL); 1453*dd11376bSBart Van Assche if (!ufs) 1454*dd11376bSBart Van Assche return -ENOMEM; 1455*dd11376bSBart Van Assche 1456*dd11376bSBart Van Assche /* exynos-specific hci */ 1457*dd11376bSBart Van Assche ufs->reg_hci = devm_platform_ioremap_resource_byname(pdev, "vs_hci"); 1458*dd11376bSBart Van Assche if (IS_ERR(ufs->reg_hci)) { 1459*dd11376bSBart Van Assche dev_err(dev, "cannot ioremap for hci vendor register\n"); 1460*dd11376bSBart Van Assche return PTR_ERR(ufs->reg_hci); 1461*dd11376bSBart Van Assche } 1462*dd11376bSBart Van Assche 1463*dd11376bSBart Van Assche ret = exynosauto_ufs_vh_wait_ph_ready(hba); 1464*dd11376bSBart Van Assche if (ret) 1465*dd11376bSBart Van Assche return ret; 1466*dd11376bSBart Van Assche 1467*dd11376bSBart Van Assche ufs->drv_data = device_get_match_data(dev); 1468*dd11376bSBart Van Assche if (!ufs->drv_data) 1469*dd11376bSBart Van Assche return -ENODEV; 1470*dd11376bSBart Van Assche 1471*dd11376bSBart Van Assche exynos_ufs_priv_init(hba, ufs); 1472*dd11376bSBart Van Assche 1473*dd11376bSBart Van Assche return 0; 1474*dd11376bSBart Van Assche } 1475*dd11376bSBart Van Assche 1476*dd11376bSBart Van Assche static struct ufs_hba_variant_ops ufs_hba_exynos_ops = { 1477*dd11376bSBart Van Assche .name = "exynos_ufs", 1478*dd11376bSBart Van Assche .init = exynos_ufs_init, 1479*dd11376bSBart Van Assche .hce_enable_notify = exynos_ufs_hce_enable_notify, 1480*dd11376bSBart Van Assche .link_startup_notify = exynos_ufs_link_startup_notify, 1481*dd11376bSBart Van Assche .pwr_change_notify = exynos_ufs_pwr_change_notify, 1482*dd11376bSBart Van Assche .setup_clocks = exynos_ufs_setup_clocks, 1483*dd11376bSBart Van Assche .setup_xfer_req = exynos_ufs_specify_nexus_t_xfer_req, 1484*dd11376bSBart Van Assche .setup_task_mgmt = exynos_ufs_specify_nexus_t_tm_req, 1485*dd11376bSBart Van Assche .hibern8_notify = exynos_ufs_hibern8_notify, 1486*dd11376bSBart Van Assche .suspend = exynos_ufs_suspend, 1487*dd11376bSBart Van Assche .resume = exynos_ufs_resume, 1488*dd11376bSBart Van Assche }; 1489*dd11376bSBart Van Assche 1490*dd11376bSBart Van Assche static struct ufs_hba_variant_ops ufs_hba_exynosauto_vh_ops = { 1491*dd11376bSBart Van Assche .name = "exynosauto_ufs_vh", 1492*dd11376bSBart Van Assche .init = exynosauto_ufs_vh_init, 1493*dd11376bSBart Van Assche .link_startup_notify = exynosauto_ufs_vh_link_startup_notify, 1494*dd11376bSBart Van Assche }; 1495*dd11376bSBart Van Assche 1496*dd11376bSBart Van Assche static int exynos_ufs_probe(struct platform_device *pdev) 1497*dd11376bSBart Van Assche { 1498*dd11376bSBart Van Assche int err; 1499*dd11376bSBart Van Assche struct device *dev = &pdev->dev; 1500*dd11376bSBart Van Assche const struct ufs_hba_variant_ops *vops = &ufs_hba_exynos_ops; 1501*dd11376bSBart Van Assche const struct exynos_ufs_drv_data *drv_data = 1502*dd11376bSBart Van Assche device_get_match_data(dev); 1503*dd11376bSBart Van Assche 1504*dd11376bSBart Van Assche if (drv_data && drv_data->vops) 1505*dd11376bSBart Van Assche vops = drv_data->vops; 1506*dd11376bSBart Van Assche 1507*dd11376bSBart Van Assche err = ufshcd_pltfrm_init(pdev, vops); 1508*dd11376bSBart Van Assche if (err) 1509*dd11376bSBart Van Assche dev_err(dev, "ufshcd_pltfrm_init() failed %d\n", err); 1510*dd11376bSBart Van Assche 1511*dd11376bSBart Van Assche return err; 1512*dd11376bSBart Van Assche } 1513*dd11376bSBart Van Assche 1514*dd11376bSBart Van Assche static int exynos_ufs_remove(struct platform_device *pdev) 1515*dd11376bSBart Van Assche { 1516*dd11376bSBart Van Assche struct ufs_hba *hba = platform_get_drvdata(pdev); 1517*dd11376bSBart Van Assche 1518*dd11376bSBart Van Assche pm_runtime_get_sync(&(pdev)->dev); 1519*dd11376bSBart Van Assche ufshcd_remove(hba); 1520*dd11376bSBart Van Assche return 0; 1521*dd11376bSBart Van Assche } 1522*dd11376bSBart Van Assche 1523*dd11376bSBart Van Assche static struct exynos_ufs_uic_attr exynos7_uic_attr = { 1524*dd11376bSBart Van Assche .tx_trailingclks = 0x10, 1525*dd11376bSBart Van Assche .tx_dif_p_nsec = 3000000, /* unit: ns */ 1526*dd11376bSBart Van Assche .tx_dif_n_nsec = 1000000, /* unit: ns */ 1527*dd11376bSBart Van Assche .tx_high_z_cnt_nsec = 20000, /* unit: ns */ 1528*dd11376bSBart Van Assche .tx_base_unit_nsec = 100000, /* unit: ns */ 1529*dd11376bSBart Van Assche .tx_gran_unit_nsec = 4000, /* unit: ns */ 1530*dd11376bSBart Van Assche .tx_sleep_cnt = 1000, /* unit: ns */ 1531*dd11376bSBart Van Assche .tx_min_activatetime = 0xa, 1532*dd11376bSBart Van Assche .rx_filler_enable = 0x2, 1533*dd11376bSBart Van Assche .rx_dif_p_nsec = 1000000, /* unit: ns */ 1534*dd11376bSBart Van Assche .rx_hibern8_wait_nsec = 4000000, /* unit: ns */ 1535*dd11376bSBart Van Assche .rx_base_unit_nsec = 100000, /* unit: ns */ 1536*dd11376bSBart Van Assche .rx_gran_unit_nsec = 4000, /* unit: ns */ 1537*dd11376bSBart Van Assche .rx_sleep_cnt = 1280, /* unit: ns */ 1538*dd11376bSBart Van Assche .rx_stall_cnt = 320, /* unit: ns */ 1539*dd11376bSBart Van Assche .rx_hs_g1_sync_len_cap = SYNC_LEN_COARSE(0xf), 1540*dd11376bSBart Van Assche .rx_hs_g2_sync_len_cap = SYNC_LEN_COARSE(0xf), 1541*dd11376bSBart Van Assche .rx_hs_g3_sync_len_cap = SYNC_LEN_COARSE(0xf), 1542*dd11376bSBart Van Assche .rx_hs_g1_prep_sync_len_cap = PREP_LEN(0xf), 1543*dd11376bSBart Van Assche .rx_hs_g2_prep_sync_len_cap = PREP_LEN(0xf), 1544*dd11376bSBart Van Assche .rx_hs_g3_prep_sync_len_cap = PREP_LEN(0xf), 1545*dd11376bSBart Van Assche .pa_dbg_option_suite = 0x30103, 1546*dd11376bSBart Van Assche }; 1547*dd11376bSBart Van Assche 1548*dd11376bSBart Van Assche static struct exynos_ufs_drv_data exynosauto_ufs_drvs = { 1549*dd11376bSBart Van Assche .uic_attr = &exynos7_uic_attr, 1550*dd11376bSBart Van Assche .quirks = UFSHCD_QUIRK_PRDT_BYTE_GRAN | 1551*dd11376bSBart Van Assche UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR | 1552*dd11376bSBart Van Assche UFSHCD_QUIRK_BROKEN_OCS_FATAL_ERROR | 1553*dd11376bSBart Van Assche UFSHCD_QUIRK_SKIP_DEF_UNIPRO_TIMEOUT_SETTING, 1554*dd11376bSBart Van Assche .opts = EXYNOS_UFS_OPT_BROKEN_AUTO_CLK_CTRL | 1555*dd11376bSBart Van Assche EXYNOS_UFS_OPT_SKIP_CONFIG_PHY_ATTR | 1556*dd11376bSBart Van Assche EXYNOS_UFS_OPT_BROKEN_RX_SEL_IDX, 1557*dd11376bSBart Van Assche .drv_init = exynosauto_ufs_drv_init, 1558*dd11376bSBart Van Assche .post_hce_enable = exynosauto_ufs_post_hce_enable, 1559*dd11376bSBart Van Assche .pre_link = exynosauto_ufs_pre_link, 1560*dd11376bSBart Van Assche .pre_pwr_change = exynosauto_ufs_pre_pwr_change, 1561*dd11376bSBart Van Assche .post_pwr_change = exynosauto_ufs_post_pwr_change, 1562*dd11376bSBart Van Assche }; 1563*dd11376bSBart Van Assche 1564*dd11376bSBart Van Assche static struct exynos_ufs_drv_data exynosauto_ufs_vh_drvs = { 1565*dd11376bSBart Van Assche .vops = &ufs_hba_exynosauto_vh_ops, 1566*dd11376bSBart Van Assche .quirks = UFSHCD_QUIRK_PRDT_BYTE_GRAN | 1567*dd11376bSBart Van Assche UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR | 1568*dd11376bSBart Van Assche UFSHCD_QUIRK_BROKEN_OCS_FATAL_ERROR | 1569*dd11376bSBart Van Assche UFSHCI_QUIRK_BROKEN_HCE | 1570*dd11376bSBart Van Assche UFSHCD_QUIRK_BROKEN_UIC_CMD | 1571*dd11376bSBart Van Assche UFSHCD_QUIRK_SKIP_PH_CONFIGURATION | 1572*dd11376bSBart Van Assche UFSHCD_QUIRK_SKIP_DEF_UNIPRO_TIMEOUT_SETTING, 1573*dd11376bSBart Van Assche .opts = EXYNOS_UFS_OPT_BROKEN_RX_SEL_IDX, 1574*dd11376bSBart Van Assche }; 1575*dd11376bSBart Van Assche 1576*dd11376bSBart Van Assche static struct exynos_ufs_drv_data exynos_ufs_drvs = { 1577*dd11376bSBart Van Assche .uic_attr = &exynos7_uic_attr, 1578*dd11376bSBart Van Assche .quirks = UFSHCD_QUIRK_PRDT_BYTE_GRAN | 1579*dd11376bSBart Van Assche UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR | 1580*dd11376bSBart Van Assche UFSHCI_QUIRK_BROKEN_HCE | 1581*dd11376bSBart Van Assche UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR | 1582*dd11376bSBart Van Assche UFSHCD_QUIRK_BROKEN_OCS_FATAL_ERROR | 1583*dd11376bSBart Van Assche UFSHCI_QUIRK_SKIP_MANUAL_WB_FLUSH_CTRL | 1584*dd11376bSBart Van Assche UFSHCD_QUIRK_SKIP_DEF_UNIPRO_TIMEOUT_SETTING | 1585*dd11376bSBart Van Assche UFSHCD_QUIRK_ALIGN_SG_WITH_PAGE_SIZE, 1586*dd11376bSBart Van Assche .opts = EXYNOS_UFS_OPT_HAS_APB_CLK_CTRL | 1587*dd11376bSBart Van Assche EXYNOS_UFS_OPT_BROKEN_AUTO_CLK_CTRL | 1588*dd11376bSBart Van Assche EXYNOS_UFS_OPT_BROKEN_RX_SEL_IDX | 1589*dd11376bSBart Van Assche EXYNOS_UFS_OPT_SKIP_CONNECTION_ESTAB | 1590*dd11376bSBart Van Assche EXYNOS_UFS_OPT_USE_SW_HIBERN8_TIMER, 1591*dd11376bSBart Van Assche .drv_init = exynos7_ufs_drv_init, 1592*dd11376bSBart Van Assche .pre_link = exynos7_ufs_pre_link, 1593*dd11376bSBart Van Assche .post_link = exynos7_ufs_post_link, 1594*dd11376bSBart Van Assche .pre_pwr_change = exynos7_ufs_pre_pwr_change, 1595*dd11376bSBart Van Assche .post_pwr_change = exynos7_ufs_post_pwr_change, 1596*dd11376bSBart Van Assche }; 1597*dd11376bSBart Van Assche 1598*dd11376bSBart Van Assche static const struct of_device_id exynos_ufs_of_match[] = { 1599*dd11376bSBart Van Assche { .compatible = "samsung,exynos7-ufs", 1600*dd11376bSBart Van Assche .data = &exynos_ufs_drvs }, 1601*dd11376bSBart Van Assche { .compatible = "samsung,exynosautov9-ufs", 1602*dd11376bSBart Van Assche .data = &exynosauto_ufs_drvs }, 1603*dd11376bSBart Van Assche { .compatible = "samsung,exynosautov9-ufs-vh", 1604*dd11376bSBart Van Assche .data = &exynosauto_ufs_vh_drvs }, 1605*dd11376bSBart Van Assche {}, 1606*dd11376bSBart Van Assche }; 1607*dd11376bSBart Van Assche 1608*dd11376bSBart Van Assche static const struct dev_pm_ops exynos_ufs_pm_ops = { 1609*dd11376bSBart Van Assche SET_SYSTEM_SLEEP_PM_OPS(ufshcd_system_suspend, ufshcd_system_resume) 1610*dd11376bSBart Van Assche SET_RUNTIME_PM_OPS(ufshcd_runtime_suspend, ufshcd_runtime_resume, NULL) 1611*dd11376bSBart Van Assche .prepare = ufshcd_suspend_prepare, 1612*dd11376bSBart Van Assche .complete = ufshcd_resume_complete, 1613*dd11376bSBart Van Assche }; 1614*dd11376bSBart Van Assche 1615*dd11376bSBart Van Assche static struct platform_driver exynos_ufs_pltform = { 1616*dd11376bSBart Van Assche .probe = exynos_ufs_probe, 1617*dd11376bSBart Van Assche .remove = exynos_ufs_remove, 1618*dd11376bSBart Van Assche .shutdown = ufshcd_pltfrm_shutdown, 1619*dd11376bSBart Van Assche .driver = { 1620*dd11376bSBart Van Assche .name = "exynos-ufshc", 1621*dd11376bSBart Van Assche .pm = &exynos_ufs_pm_ops, 1622*dd11376bSBart Van Assche .of_match_table = of_match_ptr(exynos_ufs_of_match), 1623*dd11376bSBart Van Assche }, 1624*dd11376bSBart Van Assche }; 1625*dd11376bSBart Van Assche module_platform_driver(exynos_ufs_pltform); 1626*dd11376bSBart Van Assche 1627*dd11376bSBart Van Assche MODULE_AUTHOR("Alim Akhtar <alim.akhtar@samsung.com>"); 1628*dd11376bSBart Van Assche MODULE_AUTHOR("Seungwon Jeon <essuuj@gmail.com>"); 1629*dd11376bSBart Van Assche MODULE_DESCRIPTION("Exynos UFS HCI Driver"); 1630*dd11376bSBart Van Assche MODULE_LICENSE("GPL v2"); 1631