Hi Akinobu, Thanks for the comments! I will put the internal functions static and check your notify suggestion. Do you know who the maintainer of UFS is? Thanks, Joao On 2/9/2016 12:05 PM, Akinobu Mita wrote: > Hi Joao, > > 2016-02-09 4:07 GMT+09:00 Joao Pinto <Joao.Pinto@xxxxxxxxxxxx>: >> diff --git a/drivers/scsi/ufs/ufshcd-dwc.c b/drivers/scsi/ufs/ufshcd-dwc.c >> new file mode 100644 >> index 0000000..b12b1a8 >> --- /dev/null >> +++ b/drivers/scsi/ufs/ufshcd-dwc.c >> @@ -0,0 +1,768 @@ >> +/* >> + * UFS Host driver for Synopsys Designware Core >> + * >> + * Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com) >> + * >> + * Authors: Joao Pinto <jpinto@xxxxxxxxxxxx> >> + * >> + * This program is free software; you can redistribute it and/or modify >> + * it under the terms of the GNU General Public License version 2 as >> + * published by the Free Software Foundation. >> + */ >> + >> +#include "ufshcd.h" >> +#include "unipro.h" >> + >> +#include "ufshcd-dwc.h" >> +#include "ufshci-dwc.h" >> + >> +/** >> + * ufshcd_dwc_program_clk_div() >> + * This function programs the clk divider value. This value is needed to >> + * provide 1 microsecond tick to unipro layer. >> + * @hba: Private Structure pointer >> + * @divider_val: clock divider value to be programmed >> + * >> + */ >> +void ufshcd_dwc_program_clk_div(struct ufs_hba *hba, u32 divider_val) >> +{ >> + ufshcd_writel(hba, divider_val, DWC_UFS_REG_HCLKDIV); >> +} >> +EXPORT_SYMBOL(ufshcd_dwc_program_clk_div); >> + >> +/** >> + * ufshcd_dwc_link_is_up() >> + * Check if link is up >> + * @hba: private structure poitner >> + * >> + * Returns 0 on success, non-zero value on failure >> + */ >> +int ufshcd_dwc_link_is_up(struct ufs_hba *hba) >> +{ >> + int dme_result = 0; >> + >> + ufshcd_dme_get(hba, UIC_ARG_MIB(VS_POWERSTATE), &dme_result); >> + >> + if (dme_result == UFSHCD_LINK_IS_UP) { >> + ufshcd_set_link_active(hba); >> + return 0; >> + } >> + >> + return 1; >> +} >> +EXPORT_SYMBOL(ufshcd_dwc_link_is_up); >> + >> +/** >> + * ufshcd_dwc_connection_setup() >> + * This function configures both the local side (host) and the peer side >> + * (device) unipro attributes to establish the connection to application/ >> + * cport. >> + * This function is not required if the hardware is properly configured to >> + * have this connection setup on reset. But invoking this function does no >> + * harm and should be fine even working with any ufs device. >> + * >> + * @hba: pointer to drivers private data >> + * >> + * Returns 0 on success non-zero value on failure >> + */ >> +int ufshcd_dwc_connection_setup(struct ufs_hba *hba) >> +{ >> + int ret = 0; >> + >> + /* Local side Configuration */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB(T_CONNECTIONSTATE), 0); >> + if (ret) >> + goto out; >> + >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB(N_DEVICEID), 0); >> + if (ret) >> + goto out; >> + >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB(N_DEVICEID_VALID), 0); >> + if (ret) >> + goto out; >> + >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB(T_PEERDEVICEID), 1); >> + if (ret) >> + goto out; >> + >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB(T_PEERCPORTID), 0); >> + if (ret) >> + goto out; >> + >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB(T_TRAFFICCLASS), 0); >> + if (ret) >> + goto out; >> + >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB(T_CPORTFLAGS), 0x6); >> + if (ret) >> + goto out; >> + >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB(T_CPORTMODE), 1); >> + if (ret) >> + goto out; >> + >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB(T_CONNECTIONSTATE), 1); >> + if (ret) >> + goto out; >> + >> + >> + /* Peer side Configuration */ >> + ret = ufshcd_dme_peer_set(hba, UIC_ARG_MIB(T_CONNECTIONSTATE), 0); >> + if (ret) >> + goto out; >> + >> + ret = ufshcd_dme_peer_set(hba, UIC_ARG_MIB(N_DEVICEID), 1); >> + if (ret) >> + goto out; >> + >> + ret = ufshcd_dme_peer_set(hba, UIC_ARG_MIB(N_DEVICEID_VALID), 1); >> + if (ret) >> + goto out; >> + >> + ret = ufshcd_dme_peer_set(hba, UIC_ARG_MIB(T_PEERDEVICEID), 1); >> + if (ret) >> + goto out; >> + >> + ret = ufshcd_dme_peer_set(hba, UIC_ARG_MIB(T_PEERCPORTID), 0); >> + if (ret) >> + goto out; >> + >> + ret = ufshcd_dme_peer_set(hba, UIC_ARG_MIB(T_TRAFFICCLASS), 0); >> + if (ret) >> + goto out; >> + >> + ret = ufshcd_dme_peer_set(hba, UIC_ARG_MIB(T_CPORTFLAGS), 0x6); >> + if (ret) >> + goto out; >> + >> + ret = ufshcd_dme_peer_set(hba, UIC_ARG_MIB(T_CPORTMODE), 1); >> + if (ret) >> + goto out; >> + >> + ret = ufshcd_dme_peer_set(hba, UIC_ARG_MIB(T_CONNECTIONSTATE), 1); >> + if (ret) >> + goto out; >> + >> +out: >> + return ret; >> +} >> + >> +/** >> + * ufshcd_dwc_setup_20bit_rmmi_lane0() >> + * This function configures Synopsys MPHY 20-bit RMMI Lane 0 >> + * @hba: Pointer to drivers structure >> + * >> + * Returns 0 on success or non-zero value on failure >> + */ >> +int ufshcd_dwc_setup_20bit_rmmi_lane0(struct ufs_hba *hba) >> +{ >> + int ret = 0; >> + >> + /* TX Reference Clock 26MHz */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(TX_REFCLKFREQ, >> + SELIND_LN0_TX), 0x01); >> + if (ret) >> + goto out; >> + >> + /* TX Configuration Clock Frequency Val; Divider setting */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(TX_CFGCLKFREQVAL, >> + SELIND_LN0_TX), 0x19); >> + if (ret) >> + goto out; >> + >> + /* RX Configuration Clock Frequency Val; Divider setting */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RX_CFGCLKFREQVAL, >> + SELIND_LN0_RX), 0x19); >> + if (ret) >> + goto out; >> + >> + /* TX 20-bit RMMI Interface */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(CFGEXTRATTR, >> + SELIND_LN0_TX), 0x12); >> + if (ret) >> + goto out; >> + >> + /* TX dither configuration */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(DITHERCTRL2, >> + SELIND_LN0_TX), 0xd6); >> + if (ret) >> + goto out; >> + >> + /* RX Reference Clock 26MHz */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RX_REFCLKFREQ, >> + SELIND_LN0_RX), 0x01); >> + if (ret) >> + goto out; >> + >> + /* RX 20-bit RMMI Interface */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(CFGWIDEINLN, >> + SELIND_LN0_RX), 2); >> + if (ret) >> + goto out; >> + >> + /* RX Squelch Detector output is routed to RX hibern8 exit signal */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(CFGRXCDR8, >> + SELIND_LN0_RX), 0x80); >> + if (ret) >> + goto out; >> + >> + /* Common block Direct Control 10 */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB(DIRECTCTRL10), 0x04); >> + if (ret) >> + goto out; >> + >> + /* Common block Direct Control 19 */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB(DIRECTCTRL19), 0x02); >> + if (ret) >> + goto out; >> + >> + /* ENARXDIRECTCFG4 */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(ENARXDIRECTCFG4, >> + SELIND_LN0_RX), 0x03); >> + if (ret) >> + goto out; >> + >> + /* CFGRXOVR8 */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(CFGRXOVR8, >> + SELIND_LN0_RX), 0x16); >> + if (ret) >> + goto out; >> + >> + /* RXDIRECTCTRL2 */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RXDIRECTCTRL2, >> + SELIND_LN0_RX), 0x42); >> + >> + if (ret) >> + goto out; >> + >> + /* ENARXDIRECTCFG3 */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(ENARXDIRECTCFG3, >> + SELIND_LN0_RX), 0xa4); >> + >> + if (ret) >> + goto out; >> + >> + /* RXCALCTRL */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RXCALCTRL, >> + SELIND_LN0_RX), 0x01); >> + if (ret) >> + goto out; >> + >> + /* ENARXDIRECTCFG2 */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(ENARXDIRECTCFG2, >> + SELIND_LN0_RX), 0x01); >> + if (ret) >> + goto out; >> + >> + /* CFGOVR4 */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(CFGRXOVR4, >> + SELIND_LN0_RX), 0x28); >> + if (ret) >> + goto out; >> + >> + /* RXSQCTRL */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RXSQCTRL, >> + SELIND_LN0_RX), 0x1E); >> + if (ret) >> + goto out; >> + >> + /* CFGOVR6 */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(CFGRXOVR6, >> + SELIND_LN0_RX), 0x2f); >> + if (ret) >> + goto out; >> + >> + /* CBPRGPLL2 */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB(CBPRGPLL2), 0x00); >> + >> +out: >> + return ret; >> +} >> + >> +/** >> + * ufshcd_dwc_setup_20bit_rmmi_lane1() >> + * This function configures Synopsys MPHY 20-bit RMMI Lane 1 >> + * @hba: Pointer to drivers structure >> + * >> + * Returns 0 on success or non-zero value on failure >> + */ >> +int ufshcd_dwc_setup_20bit_rmmi_lane1(struct ufs_hba *hba) >> +{ >> + int connected_rx_lanes = 0; >> + int connected_tx_lanes = 0; >> + int ret = 0; >> + >> + /* Get the available lane count */ >> + ufshcd_dme_get(hba, UIC_ARG_MIB(PA_CONNECTEDRXDATALANES), >> + &connected_rx_lanes); >> + ufshcd_dme_get(hba, UIC_ARG_MIB(PA_CONNECTEDTXDATALANES), >> + &connected_tx_lanes); >> + >> + if (connected_tx_lanes == 2) { >> + >> + /* TX Reference Clock 26MHz */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(TX_REFCLKFREQ, >> + SELIND_LN1_TX), 0x0d); >> + if (ret) >> + goto out; >> + >> + /* TX Configuration Clock Frequency Val; Divider setting */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(TX_CFGCLKFREQVAL, >> + SELIND_LN1_TX), 0x19); >> + if (ret) >> + goto out; >> + >> + /* TX 20-bit RMMI Interface */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(CFGEXTRATTR, >> + SELIND_LN1_TX), 0x12); >> + if (ret) >> + goto out; >> + >> + /* TX dither configuration */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(DITHERCTRL2, >> + SELIND_LN0_TX), 0xd6); >> + if (ret) >> + goto out; >> + } >> + >> + if (connected_rx_lanes == 2) { >> + >> + /* RX Reference Clock 26MHz */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RX_REFCLKFREQ, >> + SELIND_LN1_RX), 0x01); >> + if (ret) >> + goto out; >> + >> + /* RX Configuration Clock Frequency Val; Divider setting */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RX_CFGCLKFREQVAL, >> + SELIND_LN1_RX), 0x19); >> + if (ret) >> + goto out; >> + >> + /* RX 20-bit RMMI Interface */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(CFGWIDEINLN, >> + SELIND_LN1_RX), 2); >> + if (ret) >> + goto out; >> + >> + /* RX Squelch Detector output is routed to RX hibern8 exit >> + * signal >> + */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(CFGRXCDR8, >> + SELIND_LN1_RX), 0x80); >> + if (ret) >> + goto out; >> + >> + /* ENARXDIRECTCFG4 */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(ENARXDIRECTCFG4, >> + SELIND_LN1_RX), 0x03); >> + if (ret) >> + goto out; >> + >> + /* CFGRXOVR8 */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(CFGRXOVR8, >> + SELIND_LN1_RX), 0x16); >> + if (ret) >> + goto out; >> + >> + /* RXDIRECTCTRL2 */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RXDIRECTCTRL2, >> + SELIND_LN1_RX), 0x42); >> + if (ret) >> + goto out; >> + >> + /* ENARXDIRECTCFG3 */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(ENARXDIRECTCFG3, >> + SELIND_LN1_RX), 0xa4); >> + if (ret) >> + goto out; >> + >> + /* RXCALCTRL */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RXCALCTRL, >> + SELIND_LN1_RX), 0x01); >> + if (ret) >> + goto out; >> + >> + /* ENARXDIRECTCFG2 */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(ENARXDIRECTCFG2, >> + SELIND_LN1_RX), 0x01); >> + if (ret) >> + goto out; >> + >> + /* CFGOVR4 */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(CFGRXOVR4, >> + SELIND_LN1_RX), 0x28); >> + if (ret) >> + goto out; >> + >> + /* RXSQCTRL */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RXSQCTRL, >> + SELIND_LN1_RX), 0x1E); >> + if (ret) >> + goto out; >> + >> + /* CFGOVR6 */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(CFGRXOVR6, >> + SELIND_LN1_RX), 0x2f); >> + if (ret) >> + goto out; >> + } >> + >> +out: >> + return ret; >> +} >> + >> +/** >> + * ufshcd_dwc_setup_20bit_rmmi() >> + * This function configures Synopsys MPHY specific atributes (20-bit RMMI) >> + * @hba: Pointer to drivers structure >> + * >> + * Returns 0 on success or non-zero value on failure >> + */ >> +int ufshcd_dwc_setup_20bit_rmmi(struct ufs_hba *hba) >> +{ >> + int ret = 0; >> + >> + /* Common block Tx Global Hibernate Exit */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB(TX_GLOBALHIBERNATE), 0x00); >> + if (ret) >> + goto out; >> + >> + /* Common block Reference Clock Mode 26MHz */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB(REFCLKMODE), 0x01); >> + if (ret) >> + goto out; >> + >> + /* Common block DCO Target Frequency MAX PWM G1:9Mpbs */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB(CDIRECTCTRL6), 0xc0); >> + if (ret) >> + goto out; >> + >> + /* Common block TX and RX Div Factor is 4 7Mbps/20 = 350KHz */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB(CBDIVFACTOR), 0x44); >> + if (ret) >> + goto out; >> + >> + /* Common Block DC0 Ctrl 5*/ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB(CBDCOCTRL5), 0x64); >> + if (ret) >> + goto out; >> + >> + /* Common Block Program Tunning*/ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB(CBPRGTUNING), 0x09); >> + if (ret) >> + goto out; >> + >> + /* Common Block Real Time Observe Select - for debugging */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB(RTOBSERVESELECT), 0x00); >> + if (ret) >> + goto out; >> + >> + /* Lane 0 configuration*/ >> + ret = ufshcd_dwc_setup_20bit_rmmi_lane0(hba); >> + if (ret) >> + goto out; >> + >> + /* Lane 1 configuration*/ >> + ret = ufshcd_dwc_setup_20bit_rmmi_lane1(hba); >> + if (ret) >> + goto out; >> + >> +out: >> + return ret; >> +} >> + >> +/** >> + * ufshcd_dwc_setup_40bit_rmmi() >> + * This function configures Synopsys MPHY specific atributes (40-bit RMMI) >> + * @hba: Pointer to drivers structure >> + * >> + * Returns 0 on success or non-zero value on failure >> + */ >> +int ufshcd_dwc_setup_40bit_rmmi(struct ufs_hba *hba) >> +{ >> + int ret = 0; >> + >> + /* Common block Tx Global Hibernate Exit */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB(TX_GLOBALHIBERNATE), 0x00); >> + if (ret) >> + goto out; >> + >> + /* Common block Reference Clock Mode 26MHz */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB(REFCLKMODE), 0x01); >> + if (ret) >> + goto out; >> + >> + /* Common block DCO Target Frequency MAX PWM G1:7Mpbs */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB(CDIRECTCTRL6), 0x80); >> + if (ret) >> + goto out; >> + >> + /* Common block TX and RX Div Factor is 4 7Mbps/40 = 175KHz */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB(CBDIVFACTOR), 0x08); >> + if (ret) >> + goto out; >> + >> + /* Common Block DC0 Ctrl 5*/ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB(CBDCOCTRL5), 0x64); >> + if (ret) >> + goto out; >> + >> + /* Common Block Program Tunning*/ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB(CBPRGTUNING), 0x09); >> + if (ret) >> + goto out; >> + >> + /* Common Block Real Time Observe Select - for debugging */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB(RTOBSERVESELECT), 0x00); >> + if (ret) >> + goto out; >> + >> + /* Lane 0 configuration*/ >> + >> + /* TX Reference Clock 26MHz */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(TX_REFCLKFREQ, >> + SELIND_LN0_TX), 0x01); >> + if (ret) >> + goto out; >> + >> + /* TX Configuration Clock Frequency Val; Divider setting */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(TX_CFGCLKFREQVAL, >> + SELIND_LN0_TX), 0x19); >> + if (ret) >> + goto out; >> + >> + /* TX 40-bit RMMI Interface */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(CFGEXTRATTR, >> + SELIND_LN0_TX), 0x14); >> + if (ret) >> + goto out; >> + >> + /* TX dither configuration */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(DITHERCTRL2, >> + SELIND_LN0_TX), 0xd6); >> + if (ret) >> + goto out; >> + >> + /* RX Reference Clock 26MHz */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RX_REFCLKFREQ, >> + SELIND_LN0_RX), 0x01); >> + if (ret) >> + goto out; >> + >> + /* RX Configuration Clock Frequency Val; Divider setting */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RX_CFGCLKFREQVAL, >> + SELIND_LN0_RX), 0x19); >> + if (ret) >> + goto out; >> + >> + /* RX 40-bit RMMI Interface */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(CFGWIDEINLN, >> + SELIND_LN0_RX), 4); >> + if (ret) >> + goto out; >> + >> + /* RX Squelch Detector output is routed to RX hibern8 exit signal */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(CFGRXCDR8, >> + SELIND_LN0_RX), 0x80); >> + if (ret) >> + goto out; >> + >> + /* RX Squelch Detector output is routed to RX hibern8 exit signal */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(CFGRXCDR8, >> + SELIND_LN0_RX), 0x80); >> + if (ret) >> + goto out; >> + >> + /* Common block Direct Control 10 */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB(DIRECTCTRL10), 0x04); >> + if (ret) >> + goto out; >> + >> + /* Common block Direct Control 19 */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB(DIRECTCTRL19), 0x02); >> + if (ret) >> + goto out; >> + >> + /* RX Squelch Detector output is routed to RX hibern8 exit signal */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(CFGRXCDR8, >> + SELIND_LN0_RX), 0x80); >> + if (ret) >> + goto out; >> + >> + /* ENARXDIRECTCFG4 */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(ENARXDIRECTCFG4, >> + SELIND_LN0_RX), 0x03); >> + if (ret) >> + goto out; >> + >> + /* CFGRXOVR8 */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(CFGRXOVR8, >> + SELIND_LN0_RX), 0x16); >> + if (ret) >> + goto out; >> + >> + /* RXDIRECTCTRL2 */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RXDIRECTCTRL2, >> + SELIND_LN0_RX), 0x42); >> + if (ret) >> + goto out; >> + >> + /* ENARXDIRECTCFG3 */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(ENARXDIRECTCFG3, >> + SELIND_LN0_RX), 0xa4); >> + if (ret) >> + goto out; >> + >> + /* RXCALCTRL */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RXCALCTRL, >> + SELIND_LN0_RX), 0x01); >> + if (ret) >> + goto out; >> + >> + /* ENARXDIRECTCFG2 */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(ENARXDIRECTCFG2, >> + SELIND_LN0_RX), 0x01); >> + if (ret) >> + goto out; >> + >> + /* CFGOVR4 */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(CFGRXOVR4, >> + SELIND_LN0_RX), 0x28); >> + if (ret) >> + goto out; >> + >> + /* RXSQCTRL */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RXSQCTRL, >> + SELIND_LN0_RX), 0x1E); >> + if (ret) >> + goto out; >> + >> + /* CFGOVR6 */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(CFGRXOVR6, >> + SELIND_LN0_RX), 0x2f); >> + if (ret) >> + goto out; >> + >> + /* CBPRGPLL2 */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB(CBPRGPLL2), 0x00); >> + if (ret) >> + goto out; >> + >> +out: >> + return ret; >> +} >> + >> +/** >> + * ufshcd_dwc_setup_mphy() >> + * This function configures Local (host) Synopsys MPHY specific attributes >> + * >> + * @hba: Pointer to drivers structure >> + * >> + * Returns 0 on success non-zero value on failure >> + */ >> +int ufshcd_dwc_setup_mphy(struct ufs_hba *hba) >> +{ >> + int ret = 0; >> + >> +#ifdef CONFIG_SCSI_UFS_DWC_40BIT_RMMI >> + dev_info(hba->dev, "Configuring MPHY 40-bit RMMI"); >> + ret = ufshcd_dwc_setup_40bit_rmmi(hba); >> + if (ret) { >> + dev_err(hba->dev, "40-bit RMMI configuration failed"); >> + goto out; >> + } >> +#else >> +#ifdef CONFIG_SCSI_UFS_DWC_20BIT_RMMI >> + dev_info(hba->dev, "Configuring MPHY 20-bit RMMI"); >> + ret = ufshcd_dwc_setup_20bit_rmmi(hba); >> + if (ret) { >> + dev_err(hba->dev, "20-bit RMMI configuration failed"); >> + goto out; >> + } >> +#endif >> +#endif >> + /* To write Shadow register bank to effective configuration block */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB(VS_MPHYCFGUPDT), 0x01); >> + if (ret) >> + goto out; >> + >> + /* To configure Debug OMC */ >> + ret = ufshcd_dme_set(hba, UIC_ARG_MIB(VS_DEBUGOMC), 0x01); >> + >> +out: >> + return ret; >> +} > > These functions are only used in this file. > > ufshcd_dwc_program_clk_div > ufshcd_dwc_link_is_up > ufshcd_dwc_connection_setup > ufshcd_dwc_setup_20bit_rmmi_lane0 > ufshcd_dwc_setup_20bit_rmmi_lane1 > ufshcd_dwc_setup_20bit_rmmi > ufshcd_dwc_setup_40bit_rmmi > ufshcd_dwc_setup_mphy > > So you can make them static functions. > >> +/** >> + * ufshcd_dwc_configuration() >> + * UFS Host DWC specific configuration >> + * @hba: private structure poitner >> + * >> + * Returns 0 on success, non-zero value on failure >> + */ >> +int ufshcd_dwc_configuration(struct ufs_hba *hba) >> +{ >> + int ret = 0; >> + >> + /* Program Clock Divider Value */ >> + ufshcd_dwc_program_clk_div(hba, UFSHCD_CLK_DIV_125); >> + >> +#ifdef CONFIG_SCSI_UFS_DWC_MPHY_TC >> + ret = ufshcd_dwc_setup_mphy(hba); >> + if (ret) { >> + dev_err(hba->dev, "MPHY configuration failed (%d)", ret); >> + goto out; >> + } >> +#endif >> + ret = ufshcd_dme_link_startup(hba); >> + if (ret) { >> + dev_err(hba->dev, "Link Startup command failed (%d)", ret); >> + goto out; >> + } >> + >> + ret = ufshcd_dwc_link_is_up(hba); >> + if (ret) { >> + dev_err(hba->dev, "Link is not up"); >> + goto out; >> + } >> + >> + ret = ufshcd_dwc_connection_setup(hba); >> + if (ret) { >> + dev_err(hba->dev, "Connection setup failed (%d)", ret); >> + goto out; >> + } >> + >> + ret = ufshcd_make_hba_operational(hba); >> + if (ret) { >> + dev_err(hba->dev, "HBA kick start failed (%d)", ret); >> + goto out; >> + } >> + >> + ret = ufshcd_verify_dev_init(hba); >> + if (ret) { >> + dev_err(hba->dev, "Device init failed (%d)", ret); >> + goto out; >> + } >> + >> + ret = ufshcd_complete_dev_init(hba); >> + if (ret) { >> + dev_err(hba->dev, "Device final init failed (%d)", ret); >> + goto out; >> + } >> + >> + ufshcd_set_ufs_dev_active(hba); >> + hba->wlun_dev_clr_ua = false; >> + >> + if (hba->ufshcd_state == UFSHCD_STATE_RESET) >> + scsi_unblock_requests(hba->host); >> + >> + hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL; >> + >> + scsi_scan_host(hba->host); >> + >> +out: >> + return ret; >> +} >> +EXPORT_SYMBOL(ufshcd_dwc_configuration); > > Do you really need this alternative initialization by > adding new custom_probe_hba() in vops? I think you only need to write > link_startup_notify() callback for ufs_dwc_hba_vops like below. > > ufshcd_dwc_link_startup_notify(struct ufs_hba *hba, > enum ufs_notify_change_status status) > { > if (status == PRE_CHANGE) { > ufshcd_dwc_program_clk_div(); > ufshcd_dwc_setup_mphy(); > } else { /* POST_CHANGE */ > err = ufshcd_dwc_link_is_up(hba); > if (err) > return err; > ufshcd_dwc_connection_setup(); > } > } > -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html