root/drivers/scsi/ufs/ufshcd-dwc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ufshcd_dwc_dme_set_attrs
  2. ufshcd_dwc_program_clk_div
  3. ufshcd_dwc_link_is_up
  4. ufshcd_dwc_connection_setup
  5. ufshcd_dwc_link_startup_notify

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * UFS Host driver for Synopsys Designware Core
   4  *
   5  * Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com)
   6  *
   7  * Authors: Joao Pinto <jpinto@synopsys.com>
   8  */
   9 
  10 #include "ufshcd.h"
  11 #include "unipro.h"
  12 
  13 #include "ufshcd-dwc.h"
  14 #include "ufshci-dwc.h"
  15 
  16 int ufshcd_dwc_dme_set_attrs(struct ufs_hba *hba,
  17                                 const struct ufshcd_dme_attr_val *v, int n)
  18 {
  19         int ret = 0;
  20         int attr_node = 0;
  21 
  22         for (attr_node = 0; attr_node < n; attr_node++) {
  23                 ret = ufshcd_dme_set_attr(hba, v[attr_node].attr_sel,
  24                         ATTR_SET_NOR, v[attr_node].mib_val, v[attr_node].peer);
  25 
  26                 if (ret)
  27                         return ret;
  28         }
  29 
  30         return 0;
  31 }
  32 EXPORT_SYMBOL(ufshcd_dwc_dme_set_attrs);
  33 
  34 /**
  35  * ufshcd_dwc_program_clk_div()
  36  * This function programs the clk divider value. This value is needed to
  37  * provide 1 microsecond tick to unipro layer.
  38  * @hba: Private Structure pointer
  39  * @divider_val: clock divider value to be programmed
  40  *
  41  */
  42 static void ufshcd_dwc_program_clk_div(struct ufs_hba *hba, u32 divider_val)
  43 {
  44         ufshcd_writel(hba, divider_val, DWC_UFS_REG_HCLKDIV);
  45 }
  46 
  47 /**
  48  * ufshcd_dwc_link_is_up()
  49  * Check if link is up
  50  * @hba: private structure pointer
  51  *
  52  * Returns 0 on success, non-zero value on failure
  53  */
  54 static int ufshcd_dwc_link_is_up(struct ufs_hba *hba)
  55 {
  56         int dme_result = 0;
  57 
  58         ufshcd_dme_get(hba, UIC_ARG_MIB(VS_POWERSTATE), &dme_result);
  59 
  60         if (dme_result == UFSHCD_LINK_IS_UP) {
  61                 ufshcd_set_link_active(hba);
  62                 return 0;
  63         }
  64 
  65         return 1;
  66 }
  67 
  68 /**
  69  * ufshcd_dwc_connection_setup()
  70  * This function configures both the local side (host) and the peer side
  71  * (device) unipro attributes to establish the connection to application/
  72  * cport.
  73  * This function is not required if the hardware is properly configured to
  74  * have this connection setup on reset. But invoking this function does no
  75  * harm and should be fine even working with any ufs device.
  76  *
  77  * @hba: pointer to drivers private data
  78  *
  79  * Returns 0 on success non-zero value on failure
  80  */
  81 static int ufshcd_dwc_connection_setup(struct ufs_hba *hba)
  82 {
  83         const struct ufshcd_dme_attr_val setup_attrs[] = {
  84                 { UIC_ARG_MIB(T_CONNECTIONSTATE), 0, DME_LOCAL },
  85                 { UIC_ARG_MIB(N_DEVICEID), 0, DME_LOCAL },
  86                 { UIC_ARG_MIB(N_DEVICEID_VALID), 0, DME_LOCAL },
  87                 { UIC_ARG_MIB(T_PEERDEVICEID), 1, DME_LOCAL },
  88                 { UIC_ARG_MIB(T_PEERCPORTID), 0, DME_LOCAL },
  89                 { UIC_ARG_MIB(T_TRAFFICCLASS), 0, DME_LOCAL },
  90                 { UIC_ARG_MIB(T_CPORTFLAGS), 0x6, DME_LOCAL },
  91                 { UIC_ARG_MIB(T_CPORTMODE), 1, DME_LOCAL },
  92                 { UIC_ARG_MIB(T_CONNECTIONSTATE), 1, DME_LOCAL },
  93                 { UIC_ARG_MIB(T_CONNECTIONSTATE), 0, DME_PEER },
  94                 { UIC_ARG_MIB(N_DEVICEID), 1, DME_PEER },
  95                 { UIC_ARG_MIB(N_DEVICEID_VALID), 1, DME_PEER },
  96                 { UIC_ARG_MIB(T_PEERDEVICEID), 1, DME_PEER },
  97                 { UIC_ARG_MIB(T_PEERCPORTID), 0, DME_PEER },
  98                 { UIC_ARG_MIB(T_TRAFFICCLASS), 0, DME_PEER },
  99                 { UIC_ARG_MIB(T_CPORTFLAGS), 0x6, DME_PEER },
 100                 { UIC_ARG_MIB(T_CPORTMODE), 1, DME_PEER },
 101                 { UIC_ARG_MIB(T_CONNECTIONSTATE), 1, DME_PEER }
 102         };
 103 
 104         return ufshcd_dwc_dme_set_attrs(hba, setup_attrs, ARRAY_SIZE(setup_attrs));
 105 }
 106 
 107 /**
 108  * ufshcd_dwc_link_startup_notify()
 109  * UFS Host DWC specific link startup sequence
 110  * @hba: private structure pointer
 111  * @status: Callback notify status
 112  *
 113  * Returns 0 on success, non-zero value on failure
 114  */
 115 int ufshcd_dwc_link_startup_notify(struct ufs_hba *hba,
 116                                         enum ufs_notify_change_status status)
 117 {
 118         int err = 0;
 119 
 120         if (status == PRE_CHANGE) {
 121                 ufshcd_dwc_program_clk_div(hba, DWC_UFS_REG_HCLKDIV_DIV_125);
 122 
 123                 if (hba->vops->phy_initialization) {
 124                         err = hba->vops->phy_initialization(hba);
 125                         if (err) {
 126                                 dev_err(hba->dev, "Phy setup failed (%d)\n",
 127                                                                         err);
 128                                 goto out;
 129                         }
 130                 }
 131         } else { /* POST_CHANGE */
 132                 err = ufshcd_dwc_link_is_up(hba);
 133                 if (err) {
 134                         dev_err(hba->dev, "Link is not up\n");
 135                         goto out;
 136                 }
 137 
 138                 err = ufshcd_dwc_connection_setup(hba);
 139                 if (err)
 140                         dev_err(hba->dev, "Connection setup failed (%d)\n",
 141                                                                         err);
 142         }
 143 
 144 out:
 145         return err;
 146 }
 147 EXPORT_SYMBOL(ufshcd_dwc_link_startup_notify);
 148 
 149 MODULE_AUTHOR("Joao Pinto <Joao.Pinto@synopsys.com>");
 150 MODULE_DESCRIPTION("UFS Host driver for Synopsys Designware Core");
 151 MODULE_LICENSE("Dual BSD/GPL");

/* [<][>][^][v][top][bottom][index][help] */