scsi: ufs: add dme operations
PATCH 5/5 scsi: ufs: add dme operations
Add uic command operations including DME_XXX series.
--- drivers/scsi/ufs/ufs-attrs.h | 129 ++++++++++++++++++++++++ drivers/scsi/ufs/ufshcd.c | 220 +++++++++++++++++++++++++++++++++++++++++- drivers/scsi/ufs/ufshcd.h | 55 +++++++++++ drivers/scsi/ufs/ufshci.h | 19 ++++ 4 files changed, 422 insertions(+), 1 deletions(-) create mode 100644 drivers/scsi/ufs/ufs-attrs.h
drivers/scsi/ufs/ufs-attrs.h new file +129 -0
@@ -0,0 +1,129 @@ +/* +* drivers/scsi/ufs/ufs-attrs.h +* +* Copyright (C) 2013 Samsung Electronics Co., Ltd. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +*/ + +#ifndef _UFS_ATTRS_H_ +#define _UFS_ATTRS_H_ + +/* +* PHY Adpater attributes +*/ +#define PA_ACTIVETXDATALANES 0x1560 +#define PA_ACTIVERXDATALANES 0x1580 +#define PA_TXTRAILINGCLOCKS 0x1564 +#define PA_PHY_TYPE 0x1500 +#define PA_AVAILTXDATALANES 0x1520 +#define PA_AVAILRXDATALANES 0x1540 +#define PA_MINRXTRAILINGCLOCKS 0x1543 +#define PA_TXPWRSTATUS 0x1567 +#define PA_RXPWRSTATUS 0x1582 +#define PA_TXFORCECLOCK 0x1562 +#define PA_TXPWRMODE 0x1563 +#define PA_LEGACYDPHYESCDL 0x1570 +#define PA_MAXTXSPEEDFAST 0x1521 +#define PA_MAXTXSPEEDSLOW 0x1522 +#define PA_MAXRXSPEEDFAST 0x1541 +#define PA_MAXRXSPEEDSLOW 0x1542 +#define PA_TXLINKSTARTUPHS 0x1544 +#define PA_TXSPEEDFAST 0x1565 +#define PA_TXSPEEDSLOW 0x1566 +#define PA_REMOTEVERINFO 0x15A0 +#define PA_TXGEAR 0x1568 +#define PA_TXTERMINATION 0x1569 +#define PA_HSSERIES 0x156A +#define PA_PWRMODE 0x1571 +#define PA_RXGEAR 0x1583 +#define PA_RXTERMINATION 0x1584 +#define PA_MAXRXPWMGEAR 0x1586 +#define PA_MAXRXHSGEAR 0x1587 +#define PA_RXHSUNTERMCAP 0x15A5 +#define PA_RXLSTERMCAP 0x15A6 +#define PA_PACPREQTIMEOUT 0x1590 +#define PA_PACPREQEOBTIMEOUT 0x1591 +#define PA_LOCALVERINFO 0x15A9 +#define PA_TACTIVATE 0x15A8 +#define PA_PACPFRAMECOUNT 0x15C0 +#define PA_PACPERRORCOUNT 0x15C1 +#define PA_PHYTESTCONTROL 0x15C2 +#define PA_PWRMODEUSERDATA0 0x15B0 +#define PA_PWRMODEUSERDATA1 0x15B1 +#define PA_PWRMODEUSERDATA2 0x15B2 +#define PA_PWRMODEUSERDATA3 0x15B3 +#define PA_PWRMODEUSERDATA4 0x15B4 +#define PA_PWRMODEUSERDATA5 0x15B5 +#define PA_PWRMODEUSERDATA6 0x15B6 +#define PA_PWRMODEUSERDATA7 0x15B7 +#define PA_PWRMODEUSERDATA8 0x15B8 +#define PA_PWRMODEUSERDATA9 0x15B9 +#define PA_PWRMODEUSERDATA10 0x15BA +#define PA_PWRMODEUSERDATA11 0x15BB +#define PA_CONNECTEDTXDATALANE 0x1561 +#define PA_CONNECTEDRXDATALANE 0x1581 +#define PA_LOGICALLANEMAP 0x15A1 +#define PA_SLEEPNOCONFIGTIME 0x15A2 +#define PA_STALLNOCONFIGTIME 0x15A3 +#define PA_SAVECONFIGTIME 0x15A4 + +/* +* Data Link Layer Attributes +*/ +#define DL_TC0TXFCTHRESHOLD 0x2040 +#define DL_FC0PROTTIMEOUTVAL 0x2041 +#define DL_TC0REPLAYTIMEOUTVAL 0x2042 +#define DL_AFC0REQTIMEOUTVAL 0x2043 +#define DL_AFC0CREDITTHRESHOLD 0x2044 +#define DL_TC0OUTACKTHRESHOLD 0x2045 +#define DL_TC1TXFCTHRESHOLD 0x2060 +#define DL_FC1PROTTIMEOUTVAL 0x2061 +#define DL_TC1REPLAYTIMEOUTVAL 0x2062 +#define DL_AFC1REQTIMEOUTVAL 0x2063 +#define DL_AFC1CREDITTHRESHOLD 0x2064 +#define DL_TC1OUTACKTHRESHOLD 0x2065 +#define DL_TXPREEMPTIONCAP 0x2000 +#define DL_TC0TXMAXSDUSIZE 0x2001 +#define DL_TC0RXINITCREDITVAL 0x2002 +#define DL_TC0TXBUFFERSIZE 0x2005 +#define DL_PEERTC0PRESENT 0x2046 +#define DL_PEERTC0RXINITCREVAL 0x2047 +#define DL_TC1TXMAXSDUSIZE 0x2003 +#define DL_TC1RXINITCREDITVAL 0x2004 +#define DL_TC1TXBUFFERSIZE 0x2006 +#define DL_PEERTC1PRESENT 0x2066 +#define DL_PEERTC1RXINITCREVAL 0x2067 + +/* +* Network Layer Attributes +*/ +#define N_DEVICEID 0x3000 +#define N_DEVICEID_VALID 0x3001 +#define N_TC0TXMAXSDUSIZE 0x3020 +#define N_TC1TXMAXSDUSIZE 0x3021 + +/* +* Transport Layer Attributes +*/ +#define T_NUMCPORTS 0x4000 +#define T_NUMTESTFEATURES 0x4001 +#define T_CONNECTIONSTATE 0x4020 +#define T_PEERDEVICEID 0x4021 +#define T_PEERCPORTID 0x4022 +#define T_TRAFFICCLASS 0x4023 +#define T_PROTOCOLID 0x4024 +#define T_CPORTFLAGS 0x4025 +#define T_TXTOKENVALUE 0x4026 +#define T_RXTOKENVALUE 0x4027 +#define T_LOCALBUFFERSPACE 0x4028 +#define T_PEERBUFFERSPACE 0x4029 +#define T_CREDITSTOSEND 0x402A +#define T_CPORTMODE 0x402B +#define T_TC0TXMAXSDUSIZE 0x4060 +#define T_TC1TXMAXSDUSIZE 0x4061 + +#endif /* _UFS_ATTRS_H_ */
drivers/scsi/ufs/ufshcd.c +219 -1
250 lines not on this page · raw message
drivers/scsi/ufs/ufshcd.h +55 -0
71 lines not on this page · raw message
drivers/scsi/ufs/ufshci.h +19 -0
@@ -124,6 +124,12 @@ enum {#define CONTROLLER_FATAL_ERROR UFS_BIT(16)#define SYSTEM_BUS_FATAL_ERROR UFS_BIT(17) +#define UFSHCD_HIBERNATE_MASK (UIC_HIBERNATE_ENTER |\ + UIC_HIBERNATE_EXIT) + +#define UFSHCD_UIC_MASK (UIC_COMMAND_COMPL |\ + UFSHCD_HIBERNATE_MASK) +#define UFSHCD_ERROR_MASK (UIC_ERROR |\ DEVICE_FATAL_ERROR |\ CONTROLLER_FATAL_ERROR |\
@@ -142,6 +148,15 @@ enum {#define DEVICE_ERROR_INDICATOR UFS_BIT(5)#define UIC_POWER_MODE_CHANGE_REQ_STATUS_MASK UFS_MASK(0x7, 8) +enum { +PWR_OK =0x0 , +PWR_LOCAL =0x01 , +PWR_REMOTE =0x02 , +PWR_BUSY =0x03 , +PWR_ERROR_CAP =0x04 , +PWR_FATAL_ERROR =0x05 , +}; +/* HCE - Host Controller Enable 34h */ #define CONTROLLER_ENABLE UFS_BIT(0)#define CONTROLLER_DISABLE 0x0
@@ -191,6 +206,10 @@ enum {#define CONFIG_RESULT_CODE_MASK 0xFF#define GENERIC_ERROR_CODE_MASK 0xFF +#define UIC_ARG_MIB_SEL (attr, sel) (((attr & 0xFFFF) << 16) |\ + (sel & 0xFFFF)) +#define UIC_ARG_ATTR_SET (type) ((type & 0xFF) << 16) +/* UIC Commands */ enum {UIC_CMD_DME_GET =0x01 ,
Signature · 1 line
1.7.0.4
Quoted 543 lines
Add uic command operations including
DME_XXXseries.Signed-off-by Seungwon Jeon <[email protected]>--- drivers/scsi/ufs/ufs-attrs.h | 129 ++++++++++++++++++++++++ drivers/scsi/ufs/ufshcd.c | 220 +++++++++++++++++++++++++++++++++++++++++- drivers/scsi/ufs/ufshcd.h | 55 +++++++++++ drivers/scsi/ufs/ufshci.h | 19 ++++ 4 files changed, 422 insertions(+), 1 deletions(-) create mode 100644 drivers/scsi/ufs/ufs-attrs.hdrivers/scsi/ufs/ufs-attrs.h new file +129
-0@@ -0,0 +1,129 @@ +/* +* drivers/scsi/ufs/ufs-attrs.h +* +* Copyright (C) 2013 Samsung Electronics Co., Ltd. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +*/ + +#ifndef _UFS_ATTRS_H_ +#define _UFS_ATTRS_H_ + +/* +* PHY Adpater attributes +*/ +#define PA_ACTIVETXDATALANES 0x1560 +#define PA_ACTIVERXDATALANES 0x1580 +#define PA_TXTRAILINGCLOCKS 0x1564 +#define PA_PHY_TYPE 0x1500 +#define PA_AVAILTXDATALANES 0x1520 +#define PA_AVAILRXDATALANES 0x1540 +#define PA_MINRXTRAILINGCLOCKS 0x1543 +#define PA_TXPWRSTATUS 0x1567 +#define PA_RXPWRSTATUS 0x1582 +#define PA_TXFORCECLOCK 0x1562 +#define PA_TXPWRMODE 0x1563 +#define PA_LEGACYDPHYESCDL 0x1570 +#define PA_MAXTXSPEEDFAST 0x1521 +#define PA_MAXTXSPEEDSLOW 0x1522 +#define PA_MAXRXSPEEDFAST 0x1541 +#define PA_MAXRXSPEEDSLOW 0x1542 +#define PA_TXLINKSTARTUPHS 0x1544 +#define PA_TXSPEEDFAST 0x1565 +#define PA_TXSPEEDSLOW 0x1566 +#define PA_REMOTEVERINFO 0x15A0 +#define PA_TXGEAR 0x1568 +#define PA_TXTERMINATION 0x1569 +#define PA_HSSERIES 0x156A +#define PA_PWRMODE 0x1571 +#define PA_RXGEAR 0x1583 +#define PA_RXTERMINATION 0x1584 +#define PA_MAXRXPWMGEAR 0x1586 +#define PA_MAXRXHSGEAR 0x1587 +#define PA_RXHSUNTERMCAP 0x15A5 +#define PA_RXLSTERMCAP 0x15A6 +#define PA_PACPREQTIMEOUT 0x1590 +#define PA_PACPREQEOBTIMEOUT 0x1591 +#define PA_LOCALVERINFO 0x15A9 +#define PA_TACTIVATE 0x15A8 +#define PA_PACPFRAMECOUNT 0x15C0 +#define PA_PACPERRORCOUNT 0x15C1 +#define PA_PHYTESTCONTROL 0x15C2 +#define PA_PWRMODEUSERDATA0 0x15B0 +#define PA_PWRMODEUSERDATA1 0x15B1 +#define PA_PWRMODEUSERDATA2 0x15B2 +#define PA_PWRMODEUSERDATA3 0x15B3 +#define PA_PWRMODEUSERDATA4 0x15B4 +#define PA_PWRMODEUSERDATA5 0x15B5 +#define PA_PWRMODEUSERDATA6 0x15B6 +#define PA_PWRMODEUSERDATA7 0x15B7 +#define PA_PWRMODEUSERDATA8 0x15B8 +#define PA_PWRMODEUSERDATA9 0x15B9 +#define PA_PWRMODEUSERDATA10 0x15BA +#define PA_PWRMODEUSERDATA11 0x15BB +#define PA_CONNECTEDTXDATALANE 0x1561 +#define PA_CONNECTEDRXDATALANE 0x1581 +#define PA_LOGICALLANEMAP 0x15A1 +#define PA_SLEEPNOCONFIGTIME 0x15A2 +#define PA_STALLNOCONFIGTIME 0x15A3 +#define PA_SAVECONFIGTIME 0x15A4 + +/* +* Data Link Layer Attributes +*/ +#define DL_TC0TXFCTHRESHOLD 0x2040 +#define DL_FC0PROTTIMEOUTVAL 0x2041 +#define DL_TC0REPLAYTIMEOUTVAL 0x2042 +#define DL_AFC0REQTIMEOUTVAL 0x2043 +#define DL_AFC0CREDITTHRESHOLD 0x2044 +#define DL_TC0OUTACKTHRESHOLD 0x2045 +#define DL_TC1TXFCTHRESHOLD 0x2060 +#define DL_FC1PROTTIMEOUTVAL 0x2061 +#define DL_TC1REPLAYTIMEOUTVAL 0x2062 +#define DL_AFC1REQTIMEOUTVAL 0x2063 +#define DL_AFC1CREDITTHRESHOLD 0x2064 +#define DL_TC1OUTACKTHRESHOLD 0x2065 +#define DL_TXPREEMPTIONCAP 0x2000 +#define DL_TC0TXMAXSDUSIZE 0x2001 +#define DL_TC0RXINITCREDITVAL 0x2002 +#define DL_TC0TXBUFFERSIZE 0x2005 +#define DL_PEERTC0PRESENT 0x2046 +#define DL_PEERTC0RXINITCREVAL 0x2047 +#define DL_TC1TXMAXSDUSIZE 0x2003 +#define DL_TC1RXINITCREDITVAL 0x2004 +#define DL_TC1TXBUFFERSIZE 0x2006 +#define DL_PEERTC1PRESENT 0x2066 +#define DL_PEERTC1RXINITCREVAL 0x2067 + +/* +* Network Layer Attributes +*/ +#define N_DEVICEID 0x3000 +#define N_DEVICEID_VALID 0x3001 +#define N_TC0TXMAXSDUSIZE 0x3020 +#define N_TC1TXMAXSDUSIZE 0x3021 + +/* +* Transport Layer Attributes +*/ +#define T_NUMCPORTS 0x4000 +#define T_NUMTESTFEATURES 0x4001 +#define T_CONNECTIONSTATE 0x4020 +#define T_PEERDEVICEID 0x4021 +#define T_PEERCPORTID 0x4022 +#define T_TRAFFICCLASS 0x4023 +#define T_PROTOCOLID 0x4024 +#define T_CPORTFLAGS 0x4025 +#define T_TXTOKENVALUE 0x4026 +#define T_RXTOKENVALUE 0x4027 +#define T_LOCALBUFFERSPACE 0x4028 +#define T_PEERBUFFERSPACE 0x4029 +#define T_CREDITSTOSEND 0x402A +#define T_CPORTMODE 0x402B +#define T_TC0TXMAXSDUSIZE 0x4060 +#define T_TC1TXMAXSDUSIZE 0x4061 + +#endif /* _UFS_ATTRS_H_ */ drivers/scsi/ufs/ufshcd.c +2
-0@@ -37,6 +37,7 @@#define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\ UTP_TASK_REQ_COMPL |\ + UFSHCD_HIBERNATE_MASK |\ UFSHCD_ERROR_MASK)#define UIC_CMD_TIMEOUT 100@@ -188,6 +189,31 @@ static inline int ufshcd_get_uic_cmd_result(struct ufs_hba *hba) }/** +* ufshcd_get_dme_attr_val - Get the value of attribute returned by UIC command
+ * @hba: Pointer to adapter instance
+ *
+ * This function gets UIC command argument3
+ * Returns 0 on success, non zero value on error
+ */drivers/scsi/ufs/ufshcd.c +208
-0+static inline u32 ufshcd_get_dme_attr_val (struct ufs_hba *hba) +{ +return ufshcd_readl (hba,REG_UIC_COMMAND_ARG_3 ); +} + + +/** +* ufshcd_get_upmcrs - Get the power mode change request status +* @hba: Pointer to adapter instance +* +* This function gets the UPMCRS field of HCS register +* Returns value of UPMCRS field +*/ +static inline u8 ufshcd_get_upmcrs (struct ufs_hba *hba) +{ +return (ufshcd_readl (hba,REG_CONTROLLER_STATUS ) >>8 ) &0x7 ; +} + +/** * ufshcd_free_hba_memory - Free allocated memory for LRB, request * and task lists * @hba: Pointer to adapter instance @@ -804,6 +830,195 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba) }/** +* ufshcd_dme_xxx_set - UIC command for DME_SET, DME_PEER_SET +* @hba: per adapter instance +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_xxx_set (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val,u8 peer) +{ +struct uic_command *uic_cmd; +static const char *const action[] = { +"dme-set" ,"dme-peer-set" + }; +const char *set = action[!!peer]; +unsigned long flags; +int ret; + +if (!ufshcd_ready_uic_cmd (hba)) +return -EIO ; + +spin_lock_irqsave (hba->host->host_lock, flags); + +/* form UIC command */ + uic_cmd = &hba->active_uic_cmd; + uic_cmd->command = peer ? +UIC_CMD_DME_PEER_SET :UIC_CMD_DME_SET ; + uic_cmd->argument1 = attr_sel; + uic_cmd->argument2 =UIC_ARG_ATTR_SET (attr_set); + uic_cmd->argument3 = mib_val; + +/* dispatch UIC commands to controller */ +ufshcd_dispatch_uic_cmd (hba, uic_cmd); +spin_unlock_irqrestore (hba->host->host_lock, flags); + + ret =ufshcd_wait_for_uic_cmd (hba); +dev_dbg (hba->dev,"%s: error code %d returned\n" , set, ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_xxx_set); + +/** +* ufshcd_dme_xxx_get - UIC command for DME_GET, DME_PEER_GET +* @hba: per adapter instance +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_xxx_get (struct ufs_hba *hba,u32 attr_sel,u32 *mib_val,u8 peer) +{ +struct uic_command *uic_cmd; +static const char *const action[] = { +"dme-get" ,"dme-peer-get" + }; +const char *get = action[!!peer]; +unsigned long flags; +int ret; + +if (!ufshcd_ready_uic_cmd (hba)) +return -EIO ; + +spin_lock_irqsave (hba->host->host_lock, flags); + +/* form UIC command */ + uic_cmd = &hba->active_uic_cmd; + uic_cmd->command = peer ? +UIC_CMD_DME_PEER_GET :UIC_CMD_DME_GET ; + uic_cmd->argument1 = attr_sel; + uic_cmd->argument2 =0 ; + uic_cmd->argument3 =0 ; + +/* dispatch UIC commands to controller */ +ufshcd_dispatch_uic_cmd (hba, uic_cmd); +spin_unlock_irqrestore (hba->host->host_lock, flags); + + ret =ufshcd_wait_for_uic_cmd (hba); +if (mib_val) + *mib_val =ufshcd_get_dme_attr_val (hba); + +dev_dbg (hba->dev,"%s: error code %d returned\n" , get, ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_xxx_get); + +/** +* ufshcd_dme_power_xxx - UIC command for DME_POWERON, DME_POWEROFF +* @hba: per adapter instance +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_power_xxx (struct ufs_hba *hba,u8 on) +{ +struct uic_command *uic_cmd; +static const char *const action[] = { +"dme-power-on" , +"dme-power-off" , + }; +const char *power = action[!!on]; +unsigned long flags; +int ret; + +if (!ufshcd_ready_uic_cmd (hba)) +return -EIO ; + +spin_lock_irqsave (hba->host->host_lock, flags); + +/* form UIC command */ + uic_cmd = &hba->active_uic_cmd; + uic_cmd->command = on ? +UIC_CMD_DME_POWERON :UIC_CMD_DME_POWEROFF ; + uic_cmd->argument1 =0 ; + uic_cmd->argument2 =0 ; + uic_cmd->argument3 =0 ; + +/* dispatch UIC commands to controller */ +ufshcd_dispatch_uic_cmd (hba, uic_cmd); + +spin_unlock_irqrestore (hba->host->host_lock, flags); + + ret =ufshcd_wait_for_uic_cmd (hba); +if (ret) +dev_err (hba->dev,"%s: error code %d returned\n" , power, ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_power_xxx); + +/** +* ufshcd_dme_hibern8_xxx - UIC command for DME_HIBERNATE_ENTER, +* DME_HIBERNATE_EXIT +* @hba: per adapter instance +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_hibern8_xxx (struct ufs_hba *hba,u8 enter) +{ +struct uic_command *uic_cmd; +static const char *const action[] = { +"dme-hibernate-enter" , +"dme-hibernate-exit" + }; +const char *hibern8 = action[!!enter]; +unsigned long flags; +u8 status; +int ret; + +if (!ufshcd_ready_uic_cmd (hba)) +return -EIO ; + +spin_lock_irqsave (hba->host->host_lock, flags); + +/* form UIC command */ + uic_cmd = &hba->active_uic_cmd; + uic_cmd->command = enter ? +UIC_CMD_DME_HIBER_ENTER :UIC_CMD_DME_HIBER_EXIT ; + uic_cmd->argument1 =0 ; + uic_cmd->argument2 =0 ; + uic_cmd->argument3 =0 ; + +/* dispatch UIC commands to controller */ +ufshcd_dispatch_uic_cmd (hba, uic_cmd); + +spin_unlock_irqrestore (hba->host->host_lock, flags); + + ret=ufshcd_wait_for_uic_cmd (hba); +if (ret) { +dev_err (hba->dev,"%s: error code %d returned\n" , hibern8, ret); + goto out; + } + +init_completion (&hba->hibern8_done); + +if (wait_for_completion_timeout (&hba->hibern8_done, +msecs_to_jiffies (UIC_CMD_TIMEOUT ))) { + status =ufshcd_get_upmcrs (hba); +if (status !=PWR_LOCAL ) { +dev_err (hba->dev,"%s: failed, host upmcrs:%x\n" , + hibern8, status); + ret = status; + } + }else { +dev_err (hba->dev,"%s: timeout\n" , hibern8); + ret = -ETIMEDOUT ; + } +out: +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_hibern8_xxx); + +/** * ufshcd_make_hba_operational - Make UFS controller operational * @hba: per adapter instance
*drivers/scsi/ufs/ufshcd.c +3
-0@@ -1238,6 +1453,9 @@ static void ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status) {if (intr_status &UIC_COMMAND_COMPL )complete (&hba->active_uic_cmd.done); + +if (intr_status &UFSHCD_HIBERNATE_MASK ) +complete (&hba->hibern8_done); }/**
drivers/scsi/ufs/ufshcd.c +1
-1@@ -1362,7 +1580,7 @@ static void ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status)if (hba->errors)ufshcd_err_handler (hba); -if (intr_status &UIC_COMMAND_COMPL ) +if (intr_status &UFSHCD_UIC_MASK )ufshcd_uic_cmd_compl (hba, intr_status);drivers/scsi/ufs/ufshcd.c +0
-0if (intr_status &UTP_TASK_REQ_COMPL )drivers/scsi/ufs/ufshcd.h +55
-0@@ -140,6 +140,7 @@ struct ufshcd_lrb {* @active_uic_cmd: handle of active UIC command * @ufshcd_tm_wait_queue: wait queue for task management * @tm_condition: condition variable for task management +* @hibern8_done: completion for hibernate * @ufshcd_state: UFSHCD states * @intr_mask: Interrupt Mask Bits * @link_startup_wq: Work queue for link start-up @@ -177,6 +178,8 @@ struct ufs_hba {wait_queue_head_t ufshcd_tm_wait_queue;unsigned long tm_condition; +struct completion hibern8_done; +u32 ufshcd_state;u32 intr_mask;@@ -197,4 +200,56 @@ void ufshcd_remove(struct ufs_hba *);#define ufshcd_readl (hba, reg) \ readl((hba)->mmio_base + (reg)) + +extern int ufshcd_dme_xxx_set (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val,u8 peer); +extern int ufshcd_dme_xxx_get (struct ufs_hba *hba,u32 attr_sel, +u32 *mib_val,u8 peer); +extern int ufshcd_dme_power_xxx (struct ufs_hba *hba,u8 on); +extern int ufshcd_dme_hibern8_xxx (struct ufs_hba *hba,u8 enter); + +static inline int ufshcd_dme_set (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val) +{ +return ufshcd_dme_xxx_set (hba, attr_sel, attr_set, mib_val,0 ); +} + +static inline int ufshcd_dme_peer_set (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val) +{ +return ufshcd_dme_xxx_set (hba, attr_sel, attr_set, mib_val,1 ); +} + +static inline int ufshcd_dme_get (struct ufs_hba *hba,u32 attr_sel, +u32 *mib_val) +{ +return ufshcd_dme_xxx_get (hba, attr_sel, mib_val,0 ); +} + +static inline int ufshcd_dme_peer_get (struct ufs_hba *hba,u32 attr_sel, +u32 *mib_val) +{ +return ufshcd_dme_xxx_get (hba, attr_sel, mib_val,1 ); +} + +static inline int ufshcd_dme_power_on (struct ufs_hba *hba) +{ +return ufshcd_dme_power_xxx (hba,1 ); +} + +static inline int ufshcd_dme_power_off (struct ufs_hba *hba) +{ +return ufshcd_dme_power_xxx (hba,0 ); +} + +static inline int ufshcd_dme_hibern8_enter (struct ufs_hba *hba,u8 enter) +{ +return ufshcd_dme_hibern8_xxx (hba,1 ); +} + +static inline int ufshcd_dme_hibern8_exit (struct ufs_hba *hba,u8 enter) +{ +return ufshcd_dme_hibern8_xxx (hba,0 ); +} +#endif /* End of Header */ drivers/scsi/ufs/ufshci.h +19
-1@@ -124,6 +124,12 @@ enum {#define CONTROLLER_FATAL_ERROR UFS_BIT(16)#define SYSTEM_BUS_FATAL_ERROR UFS_BIT(17) +#define UFSHCD_HIBERNATE_MASK (UIC_HIBERNATE_ENTER |\ + UIC_HIBERNATE_EXIT) + +#define UFSHCD_UIC_MASK (UIC_COMMAND_COMPL |\ + UFSHCD_HIBERNATE_MASK) +#define UFSHCD_ERROR_MASK (UIC_ERROR |\ DEVICE_FATAL_ERROR |\ CONTROLLER_FATAL_ERROR |\@@ -142,6 +148,15 @@ enum {#define DEVICE_ERROR_INDICATOR UFS_BIT(5)#define UIC_POWER_MODE_CHANGE_REQ_STATUS_MASK UFS_MASK(0x7, 8) +enum { +PWR_OK =0x0 , +PWR_LOCAL =0x01 , +PWR_REMOTE =0x02 , +PWR_BUSY =0x03 , +PWR_ERROR_CAP =0x04 , +PWR_FATAL_ERROR =0x05 , +}; +/* HCE - Host Controller Enable 34h */ #define CONTROLLER_ENABLE UFS_BIT(0)#define CONTROLLER_DISABLE 0x0@@ -191,6 +206,10 @@ enum {#define CONFIG_RESULT_CODE_MASK 0xFF#define GENERIC_ERROR_CODE_MASK 0xFF +#define UIC_ARG_MIB_SEL (attr, sel) (((attr & 0xFFFF) << 16) |\ + (sel & 0xFFFF)) +#define UIC_ARG_ATTR_SET (type) ((type & 0xFF) << 16) +/* UIC Commands */ enum {UIC_CMD_DME_GET =0x01 , --1.7.0.4
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 3 lines
Maya Erez QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
Quoted 119 lines
drivers/scsi/ufs/ufs-attrs.h new file +119
-0+/* +* drivers/scsi/ufs/ufs-attrs.h +* +* Copyright (C) 2013 Samsung Electronics Co., Ltd. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +*/ + +#ifndef _UFS_ATTRS_H_ +#define _UFS_ATTRS_H_ + +/* +* PHY Adpater attributes +*/ +#define PA_ACTIVETXDATALANES 0x1560 +#define PA_ACTIVERXDATALANES 0x1580 +#define PA_TXTRAILINGCLOCKS 0x1564 +#define PA_PHY_TYPE 0x1500 +#define PA_AVAILTXDATALANES 0x1520 +#define PA_AVAILRXDATALANES 0x1540 +#define PA_MINRXTRAILINGCLOCKS 0x1543 +#define PA_TXPWRSTATUS 0x1567 +#define PA_RXPWRSTATUS 0x1582 +#define PA_TXFORCECLOCK 0x1562 +#define PA_TXPWRMODE 0x1563 +#define PA_LEGACYDPHYESCDL 0x1570 +#define PA_MAXTXSPEEDFAST 0x1521 +#define PA_MAXTXSPEEDSLOW 0x1522 +#define PA_MAXRXSPEEDFAST 0x1541 +#define PA_MAXRXSPEEDSLOW 0x1542 +#define PA_TXLINKSTARTUPHS 0x1544 +#define PA_TXSPEEDFAST 0x1565 +#define PA_TXSPEEDSLOW 0x1566 +#define PA_REMOTEVERINFO 0x15A0 +#define PA_TXGEAR 0x1568 +#define PA_TXTERMINATION 0x1569 +#define PA_HSSERIES 0x156A +#define PA_PWRMODE 0x1571 +#define PA_RXGEAR 0x1583 +#define PA_RXTERMINATION 0x1584 +#define PA_MAXRXPWMGEAR 0x1586 +#define PA_MAXRXHSGEAR 0x1587 +#define PA_RXHSUNTERMCAP 0x15A5 +#define PA_RXLSTERMCAP 0x15A6 +#define PA_PACPREQTIMEOUT 0x1590 +#define PA_PACPREQEOBTIMEOUT 0x1591 +#define PA_LOCALVERINFO 0x15A9 +#define PA_TACTIVATE 0x15A8 +#define PA_PACPFRAMECOUNT 0x15C0 +#define PA_PACPERRORCOUNT 0x15C1 +#define PA_PHYTESTCONTROL 0x15C2 +#define PA_PWRMODEUSERDATA0 0x15B0 +#define PA_PWRMODEUSERDATA1 0x15B1 +#define PA_PWRMODEUSERDATA2 0x15B2 +#define PA_PWRMODEUSERDATA3 0x15B3 +#define PA_PWRMODEUSERDATA4 0x15B4 +#define PA_PWRMODEUSERDATA5 0x15B5 +#define PA_PWRMODEUSERDATA6 0x15B6 +#define PA_PWRMODEUSERDATA7 0x15B7 +#define PA_PWRMODEUSERDATA8 0x15B8 +#define PA_PWRMODEUSERDATA9 0x15B9 +#define PA_PWRMODEUSERDATA10 0x15BA +#define PA_PWRMODEUSERDATA11 0x15BB +#define PA_CONNECTEDTXDATALANE 0x1561 +#define PA_CONNECTEDRXDATALANE 0x1581 +#define PA_LOGICALLANEMAP 0x15A1 +#define PA_SLEEPNOCONFIGTIME 0x15A2 +#define PA_STALLNOCONFIGTIME 0x15A3 +#define PA_SAVECONFIGTIME 0x15A4 + +/* +* Data Link Layer Attributes +*/ +#define DL_TC0TXFCTHRESHOLD 0x2040 +#define DL_FC0PROTTIMEOUTVAL 0x2041 +#define DL_TC0REPLAYTIMEOUTVAL 0x2042 +#define DL_AFC0REQTIMEOUTVAL 0x2043 +#define DL_AFC0CREDITTHRESHOLD 0x2044 +#define DL_TC0OUTACKTHRESHOLD 0x2045 +#define DL_TC1TXFCTHRESHOLD 0x2060 +#define DL_FC1PROTTIMEOUTVAL 0x2061 +#define DL_TC1REPLAYTIMEOUTVAL 0x2062 +#define DL_AFC1REQTIMEOUTVAL 0x2063 +#define DL_AFC1CREDITTHRESHOLD 0x2064 +#define DL_TC1OUTACKTHRESHOLD 0x2065 +#define DL_TXPREEMPTIONCAP 0x2000 +#define DL_TC0TXMAXSDUSIZE 0x2001 +#define DL_TC0RXINITCREDITVAL 0x2002 +#define DL_TC0TXBUFFERSIZE 0x2005 +#define DL_PEERTC0PRESENT 0x2046 +#define DL_PEERTC0RXINITCREVAL 0x2047 +#define DL_TC1TXMAXSDUSIZE 0x2003 +#define DL_TC1RXINITCREDITVAL 0x2004 +#define DL_TC1TXBUFFERSIZE 0x2006 +#define DL_PEERTC1PRESENT 0x2066 +#define DL_PEERTC1RXINITCREVAL 0x2067 + +/* +* Network Layer Attributes +*/ +#define N_DEVICEID 0x3000 +#define N_DEVICEID_VALID 0x3001 +#define N_TC0TXMAXSDUSIZE 0x3020 +#define N_TC1TXMAXSDUSIZE 0x3021 + +/* +* Transport Layer Attributes +*/ +#define T_NUMCPORTS 0x4000 +#define T_NUMTESTFEATURES 0x4001 +#define T_CONNECTIONSTATE 0x4020 +#define T_PEERDEVICEID 0x4021 +#define T_PEERCPORTID 0x4022 +#define T_TRAFFICCLASS 0x4023 +#define T_PROTOCOLID 0x4024 +#define T_CPORTFLAGS 0x4025
drivers/scsi/ufs/ufs-attrs.h line 129
Quoted 10 lines
drivers/scsi/ufs/ufs-attrs.h new file +10
-0+#define T_TXTOKENVALUE 0x4026 +#define T_RXTOKENVALUE 0x4027 +#define T_LOCALBUFFERSPACE 0x4028 +#define T_PEERBUFFERSPACE 0x4029 +#define T_CREDITSTOSEND 0x402A +#define T_CPORTMODE 0x402B +#define T_TC0TXMAXSDUSIZE 0x4060 +#define T_TC1TXMAXSDUSIZE 0x4061 + +#endif /* _UFS_ATTRS_H_ */
These are Unipro. So change the name of the file to unipro.h
Quoted 15 lines
drivers/scsi/ufs/ufshcd.c +1
-0@@ -37,6 +37,7 @@#define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\ UTP_TASK_REQ_COMPL |\ + UFSHCD_HIBERNATE_MASK |\ UFSHCD_ERROR_MASK)#define UIC_CMD_TIMEOUT 100@@ -188,6 +189,31 @@ static inline int ufshcd_get_uic_cmd_result(struct ufs_hba *hba) }
Signature · 1 line
~Santosh
Quoted 124 lines · Santosh Y
Quoted 124 lines
drivers/scsi/ufs/ufs-attrs.h new file +124
-0+/* +* drivers/scsi/ufs/ufs-attrs.h +* +* Copyright (C) 2013 Samsung Electronics Co., Ltd. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +*/ + +#ifndef _UFS_ATTRS_H_ +#define _UFS_ATTRS_H_ + +/* +* PHY Adpater attributes +*/ +#define PA_ACTIVETXDATALANES 0x1560 +#define PA_ACTIVERXDATALANES 0x1580 +#define PA_TXTRAILINGCLOCKS 0x1564 +#define PA_PHY_TYPE 0x1500 +#define PA_AVAILTXDATALANES 0x1520 +#define PA_AVAILRXDATALANES 0x1540 +#define PA_MINRXTRAILINGCLOCKS 0x1543 +#define PA_TXPWRSTATUS 0x1567 +#define PA_RXPWRSTATUS 0x1582 +#define PA_TXFORCECLOCK 0x1562 +#define PA_TXPWRMODE 0x1563 +#define PA_LEGACYDPHYESCDL 0x1570 +#define PA_MAXTXSPEEDFAST 0x1521 +#define PA_MAXTXSPEEDSLOW 0x1522 +#define PA_MAXRXSPEEDFAST 0x1541 +#define PA_MAXRXSPEEDSLOW 0x1542 +#define PA_TXLINKSTARTUPHS 0x1544 +#define PA_TXSPEEDFAST 0x1565 +#define PA_TXSPEEDSLOW 0x1566 +#define PA_REMOTEVERINFO 0x15A0 +#define PA_TXGEAR 0x1568 +#define PA_TXTERMINATION 0x1569 +#define PA_HSSERIES 0x156A +#define PA_PWRMODE 0x1571 +#define PA_RXGEAR 0x1583 +#define PA_RXTERMINATION 0x1584 +#define PA_MAXRXPWMGEAR 0x1586 +#define PA_MAXRXHSGEAR 0x1587 +#define PA_RXHSUNTERMCAP 0x15A5 +#define PA_RXLSTERMCAP 0x15A6 +#define PA_PACPREQTIMEOUT 0x1590 +#define PA_PACPREQEOBTIMEOUT 0x1591 +#define PA_LOCALVERINFO 0x15A9 +#define PA_TACTIVATE 0x15A8 +#define PA_PACPFRAMECOUNT 0x15C0 +#define PA_PACPERRORCOUNT 0x15C1 +#define PA_PHYTESTCONTROL 0x15C2 +#define PA_PWRMODEUSERDATA0 0x15B0 +#define PA_PWRMODEUSERDATA1 0x15B1 +#define PA_PWRMODEUSERDATA2 0x15B2 +#define PA_PWRMODEUSERDATA3 0x15B3 +#define PA_PWRMODEUSERDATA4 0x15B4 +#define PA_PWRMODEUSERDATA5 0x15B5 +#define PA_PWRMODEUSERDATA6 0x15B6 +#define PA_PWRMODEUSERDATA7 0x15B7 +#define PA_PWRMODEUSERDATA8 0x15B8 +#define PA_PWRMODEUSERDATA9 0x15B9 +#define PA_PWRMODEUSERDATA10 0x15BA +#define PA_PWRMODEUSERDATA11 0x15BB +#define PA_CONNECTEDTXDATALANE 0x1561 +#define PA_CONNECTEDRXDATALANE 0x1581 +#define PA_LOGICALLANEMAP 0x15A1 +#define PA_SLEEPNOCONFIGTIME 0x15A2 +#define PA_STALLNOCONFIGTIME 0x15A3 +#define PA_SAVECONFIGTIME 0x15A4 + +/* +* Data Link Layer Attributes +*/ +#define DL_TC0TXFCTHRESHOLD 0x2040 +#define DL_FC0PROTTIMEOUTVAL 0x2041 +#define DL_TC0REPLAYTIMEOUTVAL 0x2042 +#define DL_AFC0REQTIMEOUTVAL 0x2043 +#define DL_AFC0CREDITTHRESHOLD 0x2044 +#define DL_TC0OUTACKTHRESHOLD 0x2045 +#define DL_TC1TXFCTHRESHOLD 0x2060 +#define DL_FC1PROTTIMEOUTVAL 0x2061 +#define DL_TC1REPLAYTIMEOUTVAL 0x2062 +#define DL_AFC1REQTIMEOUTVAL 0x2063 +#define DL_AFC1CREDITTHRESHOLD 0x2064 +#define DL_TC1OUTACKTHRESHOLD 0x2065 +#define DL_TXPREEMPTIONCAP 0x2000 +#define DL_TC0TXMAXSDUSIZE 0x2001 +#define DL_TC0RXINITCREDITVAL 0x2002 +#define DL_TC0TXBUFFERSIZE 0x2005 +#define DL_PEERTC0PRESENT 0x2046 +#define DL_PEERTC0RXINITCREVAL 0x2047 +#define DL_TC1TXMAXSDUSIZE 0x2003 +#define DL_TC1RXINITCREDITVAL 0x2004 +#define DL_TC1TXBUFFERSIZE 0x2006 +#define DL_PEERTC1PRESENT 0x2066 +#define DL_PEERTC1RXINITCREVAL 0x2067 + +/* +* Network Layer Attributes +*/ +#define N_DEVICEID 0x3000 +#define N_DEVICEID_VALID 0x3001 +#define N_TC0TXMAXSDUSIZE 0x3020 +#define N_TC1TXMAXSDUSIZE 0x3021 + +/* +* Transport Layer Attributes +*/ +#define T_NUMCPORTS 0x4000 +#define T_NUMTESTFEATURES 0x4001 +#define T_CONNECTIONSTATE 0x4020 +#define T_PEERDEVICEID 0x4021 +#define T_PEERCPORTID 0x4022 +#define T_TRAFFICCLASS 0x4023 +#define T_PROTOCOLID 0x4024 +#define T_CPORTFLAGS 0x4025 +#define T_TXTOKENVALUE 0x4026 +#define T_RXTOKENVALUE 0x4027 +#define T_LOCALBUFFERSPACE 0x4028 +#define T_PEERBUFFERSPACE 0x4029 +#define T_CREDITSTOSEND 0x402A
Quoted 9 lines
drivers/scsi/ufs/ufs-attrs.h line 129
Quoted 5 lines
drivers/scsi/ufs/ufs-attrs.h new file +5
-0+#define T_CPORTMODE 0x402B +#define T_TC0TXMAXSDUSIZE 0x4060 +#define T_TC1TXMAXSDUSIZE 0x4061 + +#endif /* _UFS_ATTRS_H_ */ These are Unipro. So change the name of the file to
unipro.h
I meant Unipro attributes, So change the name accordingly.
Quoted 19 lines
Quoted 13 lines
drivers/scsi/ufs/ufshcd.c +1
-0@@ -37,6 +37,7 @@#define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\ UTP_TASK_REQ_COMPL |\ + UFSHCD_HIBERNATE_MASK |\ UFSHCD_ERROR_MASK)#define UIC_CMD_TIMEOUT 100drivers/scsi/ufs/ufshcd.c static inline int ufshcd_get_uic_cmd_result(struct ufs_hba *hba) · line 190
Quoted 2 lines
drivers/scsi/ufs/ufshcd.c +0
-0@@ -188,6 +189,31 @@ static inline int ufshcd_get_uic_cmd_result(struct ufs_hba *hba) }--
~Santosh
Signature · 1 line
~Santosh
Quoted 134 lines · On Thursday, May 02, 2013 Santosh Y wrote:
Quoted 124 lines · Santosh Y
Quoted 124 lines
drivers/scsi/ufs/ufs-attrs.h new file +124
-0+/* +* drivers/scsi/ufs/ufs-attrs.h +* +* Copyright (C) 2013 Samsung Electronics Co., Ltd. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +*/ + +#ifndef _UFS_ATTRS_H_ +#define _UFS_ATTRS_H_ + +/* +* PHY Adpater attributes +*/ +#define PA_ACTIVETXDATALANES 0x1560 +#define PA_ACTIVERXDATALANES 0x1580 +#define PA_TXTRAILINGCLOCKS 0x1564 +#define PA_PHY_TYPE 0x1500 +#define PA_AVAILTXDATALANES 0x1520 +#define PA_AVAILRXDATALANES 0x1540 +#define PA_MINRXTRAILINGCLOCKS 0x1543 +#define PA_TXPWRSTATUS 0x1567 +#define PA_RXPWRSTATUS 0x1582 +#define PA_TXFORCECLOCK 0x1562 +#define PA_TXPWRMODE 0x1563 +#define PA_LEGACYDPHYESCDL 0x1570 +#define PA_MAXTXSPEEDFAST 0x1521 +#define PA_MAXTXSPEEDSLOW 0x1522 +#define PA_MAXRXSPEEDFAST 0x1541 +#define PA_MAXRXSPEEDSLOW 0x1542 +#define PA_TXLINKSTARTUPHS 0x1544 +#define PA_TXSPEEDFAST 0x1565 +#define PA_TXSPEEDSLOW 0x1566 +#define PA_REMOTEVERINFO 0x15A0 +#define PA_TXGEAR 0x1568 +#define PA_TXTERMINATION 0x1569 +#define PA_HSSERIES 0x156A +#define PA_PWRMODE 0x1571 +#define PA_RXGEAR 0x1583 +#define PA_RXTERMINATION 0x1584 +#define PA_MAXRXPWMGEAR 0x1586 +#define PA_MAXRXHSGEAR 0x1587 +#define PA_RXHSUNTERMCAP 0x15A5 +#define PA_RXLSTERMCAP 0x15A6 +#define PA_PACPREQTIMEOUT 0x1590 +#define PA_PACPREQEOBTIMEOUT 0x1591 +#define PA_LOCALVERINFO 0x15A9 +#define PA_TACTIVATE 0x15A8 +#define PA_PACPFRAMECOUNT 0x15C0 +#define PA_PACPERRORCOUNT 0x15C1 +#define PA_PHYTESTCONTROL 0x15C2 +#define PA_PWRMODEUSERDATA0 0x15B0 +#define PA_PWRMODEUSERDATA1 0x15B1 +#define PA_PWRMODEUSERDATA2 0x15B2 +#define PA_PWRMODEUSERDATA3 0x15B3 +#define PA_PWRMODEUSERDATA4 0x15B4 +#define PA_PWRMODEUSERDATA5 0x15B5 +#define PA_PWRMODEUSERDATA6 0x15B6 +#define PA_PWRMODEUSERDATA7 0x15B7 +#define PA_PWRMODEUSERDATA8 0x15B8 +#define PA_PWRMODEUSERDATA9 0x15B9 +#define PA_PWRMODEUSERDATA10 0x15BA +#define PA_PWRMODEUSERDATA11 0x15BB +#define PA_CONNECTEDTXDATALANE 0x1561 +#define PA_CONNECTEDRXDATALANE 0x1581 +#define PA_LOGICALLANEMAP 0x15A1 +#define PA_SLEEPNOCONFIGTIME 0x15A2 +#define PA_STALLNOCONFIGTIME 0x15A3 +#define PA_SAVECONFIGTIME 0x15A4 + +/* +* Data Link Layer Attributes +*/ +#define DL_TC0TXFCTHRESHOLD 0x2040 +#define DL_FC0PROTTIMEOUTVAL 0x2041 +#define DL_TC0REPLAYTIMEOUTVAL 0x2042 +#define DL_AFC0REQTIMEOUTVAL 0x2043 +#define DL_AFC0CREDITTHRESHOLD 0x2044 +#define DL_TC0OUTACKTHRESHOLD 0x2045 +#define DL_TC1TXFCTHRESHOLD 0x2060 +#define DL_FC1PROTTIMEOUTVAL 0x2061 +#define DL_TC1REPLAYTIMEOUTVAL 0x2062 +#define DL_AFC1REQTIMEOUTVAL 0x2063 +#define DL_AFC1CREDITTHRESHOLD 0x2064 +#define DL_TC1OUTACKTHRESHOLD 0x2065 +#define DL_TXPREEMPTIONCAP 0x2000 +#define DL_TC0TXMAXSDUSIZE 0x2001 +#define DL_TC0RXINITCREDITVAL 0x2002 +#define DL_TC0TXBUFFERSIZE 0x2005 +#define DL_PEERTC0PRESENT 0x2046 +#define DL_PEERTC0RXINITCREVAL 0x2047 +#define DL_TC1TXMAXSDUSIZE 0x2003 +#define DL_TC1RXINITCREDITVAL 0x2004 +#define DL_TC1TXBUFFERSIZE 0x2006 +#define DL_PEERTC1PRESENT 0x2066 +#define DL_PEERTC1RXINITCREVAL 0x2067 + +/* +* Network Layer Attributes +*/ +#define N_DEVICEID 0x3000 +#define N_DEVICEID_VALID 0x3001 +#define N_TC0TXMAXSDUSIZE 0x3020 +#define N_TC1TXMAXSDUSIZE 0x3021 + +/* +* Transport Layer Attributes +*/ +#define T_NUMCPORTS 0x4000 +#define T_NUMTESTFEATURES 0x4001 +#define T_CONNECTIONSTATE 0x4020 +#define T_PEERDEVICEID 0x4021 +#define T_PEERCPORTID 0x4022 +#define T_TRAFFICCLASS 0x4023 +#define T_PROTOCOLID 0x4024 +#define T_CPORTFLAGS 0x4025 +#define T_TXTOKENVALUE 0x4026 +#define T_RXTOKENVALUE 0x4027 +#define T_LOCALBUFFERSPACE 0x4028 +#define T_PEERBUFFERSPACE 0x4029 +#define T_CREDITSTOSEND 0x402AQuoted 9 lines
drivers/scsi/ufs/ufs-attrs.h line 129
Quoted 5 lines
drivers/scsi/ufs/ufs-attrs.h new file +5
-0+#define T_CPORTMODE 0x402B +#define T_TC0TXMAXSDUSIZE 0x4060 +#define T_TC1TXMAXSDUSIZE 0x4061 + +#endif /* _UFS_ATTRS_H_ */ These are Unipro. So change the name of the file to
unipro.h
Quoted 1 line
I meant Unipro attributes, So change the name accordingly.
Ok, unipro.h seems proper.
Thanks,
Seungwon Jeon
Quoted 29 lines
Quoted 13 lines
Quoted 13 lines
drivers/scsi/ufs/ufshcd.c +1
-0@@ -37,6 +37,7 @@#define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\ UTP_TASK_REQ_COMPL |\ + UFSHCD_HIBERNATE_MASK |\ UFSHCD_ERROR_MASK)#define UIC_CMD_TIMEOUT 100Quoted 7 lines
drivers/scsi/ufs/ufshcd.c static inline int ufshcd_get_uic_cmd_result(struct ufs_hba *hba) · line 190
Quoted 3 lines
drivers/scsi/ufs/ufshcd.c +0
-0@@ -188,6 +189,31 @@ static inline int ufshcd_get_uic_cmd_result(struct ufs_hba *hba) }--
~Santosh--
~Santosh
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 20 lines · Seungwon Jeon
Add uic command operations including
DME_XXXseries.Signed-off-by Seungwon Jeon <[email protected]>--- drivers/scsi/ufs/ufs-attrs.h | 129 ++++++++++++++++++++++++ drivers/scsi/ufs/ufshcd.c | 220 +++++++++++++++++++++++++++++++++++++++++- drivers/scsi/ufs/ufshcd.h | 55 +++++++++++ drivers/scsi/ufs/ufshci.h | 19 ++++ 4 files changed, 422 insertions(+), 1 deletions(-)create mode 100644
drivers/scsi/ufs/ufs-attrs.hdrivers/scsi/ufs/ufs-attrs.h new file +3
-0@@ -0,0 +1,129 @@ +/* +* drivers/scsi/ufs/ufs-attrs.h +*
drivers/scsi/ufs/ufs-attrs.h line 13
Quoted 10 lines
drivers/scsi/ufs/ufs-attrs.h new file +10
-0+* Copyright (C) 2013 Samsung Electronics Co., Ltd. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +*/ + +#ifndef _UFS_ATTRS_H_ +#define _UFS_ATTRS_H_
I don't see a need to add this file as part of this patch as there are no users of the same in this patch. So its better to remove from here and add it as separate patch when their real use arises.
Quoted 134 lines
drivers/scsi/ufs/ufs-attrs.h new file +116
-0+ +/* +* PHY Adpater attributes +*/ +#define PA_ACTIVETXDATALANES 0x1560 +#define PA_ACTIVERXDATALANES 0x1580 +#define PA_TXTRAILINGCLOCKS 0x1564 +#define PA_PHY_TYPE 0x1500 +#define PA_AVAILTXDATALANES 0x1520 +#define PA_AVAILRXDATALANES 0x1540 +#define PA_MINRXTRAILINGCLOCKS 0x1543 +#define PA_TXPWRSTATUS 0x1567 +#define PA_RXPWRSTATUS 0x1582 +#define PA_TXFORCECLOCK 0x1562 +#define PA_TXPWRMODE 0x1563 +#define PA_LEGACYDPHYESCDL 0x1570 +#define PA_MAXTXSPEEDFAST 0x1521 +#define PA_MAXTXSPEEDSLOW 0x1522 +#define PA_MAXRXSPEEDFAST 0x1541 +#define PA_MAXRXSPEEDSLOW 0x1542 +#define PA_TXLINKSTARTUPHS 0x1544 +#define PA_TXSPEEDFAST 0x1565 +#define PA_TXSPEEDSLOW 0x1566 +#define PA_REMOTEVERINFO 0x15A0 +#define PA_TXGEAR 0x1568 +#define PA_TXTERMINATION 0x1569 +#define PA_HSSERIES 0x156A +#define PA_PWRMODE 0x1571 +#define PA_RXGEAR 0x1583 +#define PA_RXTERMINATION 0x1584 +#define PA_MAXRXPWMGEAR 0x1586 +#define PA_MAXRXHSGEAR 0x1587 +#define PA_RXHSUNTERMCAP 0x15A5 +#define PA_RXLSTERMCAP 0x15A6 +#define PA_PACPREQTIMEOUT 0x1590 +#define PA_PACPREQEOBTIMEOUT 0x1591 +#define PA_LOCALVERINFO 0x15A9 +#define PA_TACTIVATE 0x15A8 +#define PA_PACPFRAMECOUNT 0x15C0 +#define PA_PACPERRORCOUNT 0x15C1 +#define PA_PHYTESTCONTROL 0x15C2 +#define PA_PWRMODEUSERDATA0 0x15B0 +#define PA_PWRMODEUSERDATA1 0x15B1 +#define PA_PWRMODEUSERDATA2 0x15B2 +#define PA_PWRMODEUSERDATA3 0x15B3 +#define PA_PWRMODEUSERDATA4 0x15B4 +#define PA_PWRMODEUSERDATA5 0x15B5 +#define PA_PWRMODEUSERDATA6 0x15B6 +#define PA_PWRMODEUSERDATA7 0x15B7 +#define PA_PWRMODEUSERDATA8 0x15B8 +#define PA_PWRMODEUSERDATA9 0x15B9 +#define PA_PWRMODEUSERDATA10 0x15BA +#define PA_PWRMODEUSERDATA11 0x15BB +#define PA_CONNECTEDTXDATALANE 0x1561 +#define PA_CONNECTEDRXDATALANE 0x1581 +#define PA_LOGICALLANEMAP 0x15A1 +#define PA_SLEEPNOCONFIGTIME 0x15A2 +#define PA_STALLNOCONFIGTIME 0x15A3 +#define PA_SAVECONFIGTIME 0x15A4 + +/* +* Data Link Layer Attributes +*/ +#define DL_TC0TXFCTHRESHOLD 0x2040 +#define DL_FC0PROTTIMEOUTVAL 0x2041 +#define DL_TC0REPLAYTIMEOUTVAL 0x2042 +#define DL_AFC0REQTIMEOUTVAL 0x2043 +#define DL_AFC0CREDITTHRESHOLD 0x2044 +#define DL_TC0OUTACKTHRESHOLD 0x2045 +#define DL_TC1TXFCTHRESHOLD 0x2060 +#define DL_FC1PROTTIMEOUTVAL 0x2061 +#define DL_TC1REPLAYTIMEOUTVAL 0x2062 +#define DL_AFC1REQTIMEOUTVAL 0x2063 +#define DL_AFC1CREDITTHRESHOLD 0x2064 +#define DL_TC1OUTACKTHRESHOLD 0x2065 +#define DL_TXPREEMPTIONCAP 0x2000 +#define DL_TC0TXMAXSDUSIZE 0x2001 +#define DL_TC0RXINITCREDITVAL 0x2002 +#define DL_TC0TXBUFFERSIZE 0x2005 +#define DL_PEERTC0PRESENT 0x2046 +#define DL_PEERTC0RXINITCREVAL 0x2047 +#define DL_TC1TXMAXSDUSIZE 0x2003 +#define DL_TC1RXINITCREDITVAL 0x2004 +#define DL_TC1TXBUFFERSIZE 0x2006 +#define DL_PEERTC1PRESENT 0x2066 +#define DL_PEERTC1RXINITCREVAL 0x2067 + +/* +* Network Layer Attributes +*/ +#define N_DEVICEID 0x3000 +#define N_DEVICEID_VALID 0x3001 +#define N_TC0TXMAXSDUSIZE 0x3020 +#define N_TC1TXMAXSDUSIZE 0x3021 + +/* +* Transport Layer Attributes +*/ +#define T_NUMCPORTS 0x4000 +#define T_NUMTESTFEATURES 0x4001 +#define T_CONNECTIONSTATE 0x4020 +#define T_PEERDEVICEID 0x4021 +#define T_PEERCPORTID 0x4022 +#define T_TRAFFICCLASS 0x4023 +#define T_PROTOCOLID 0x4024 +#define T_CPORTFLAGS 0x4025 +#define T_TXTOKENVALUE 0x4026 +#define T_RXTOKENVALUE 0x4027 +#define T_LOCALBUFFERSPACE 0x4028 +#define T_PEERBUFFERSPACE 0x4029 +#define T_CREDITSTOSEND 0x402A +#define T_CPORTMODE 0x402B +#define T_TC0TXMAXSDUSIZE 0x4060 +#define T_TC1TXMAXSDUSIZE 0x4061 + +#endif /* _UFS_ATTRS_H_ */ drivers/scsi/ufs/ufshcd.c +3
-0@@ -37,6 +37,7 @@#define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\ UTP_TASK_REQ_COMPL |\ + UFSHCD_HIBERNATE_MASK |\ UFSHCD_ERROR_MASK)#define UIC_CMD_TIMEOUT 100@@ -188,6 +189,31 @@ static inline int ufshcd_get_uic_cmd_result(struct ufs_hba *hba) }/** +* ufshcd_get_dme_attr_val - Get the value of attribute returned by UIC command +* @hba: Pointer to adapter instance
drivers/scsi/ufs/ufshcd.c static inline int ufshcd_get_uic_cmd_result(struct ufs_hba *hba) · line 203
Quoted 10 lines
drivers/scsi/ufs/ufshcd.c +10
-0+* +* This function gets UIC command argument3 +* Returns 0 on success, non zero value on error +*/ +static inline u32 ufshcd_get_dme_attr_val (struct ufs_hba *hba) +{ +return ufshcd_readl (hba,REG_UIC_COMMAND_ARG_3 ); +} + +
Please remove one extra line space above.
Quoted 353 lines
drivers/scsi/ufs/ufshcd.c +206
-1+/** +* ufshcd_get_upmcrs - Get the power mode change request status +* @hba: Pointer to adapter instance +* +* This function gets the UPMCRS field of HCS register +* Returns value of UPMCRS field +*/ +static inline u8 ufshcd_get_upmcrs (struct ufs_hba *hba) +{ +return (ufshcd_readl (hba,REG_CONTROLLER_STATUS ) >>8 ) &0x7 ; +} + +/** * ufshcd_free_hba_memory - Free allocated memory for LRB, request * and task lists * @hba: Pointer to adapter instance @@ -804,6 +830,195 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba) }/** +* ufshcd_dme_xxx_set - UIC command for DME_SET, DME_PEER_SET +* @hba: per adapter instance +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_xxx_set (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val,u8 peer) +{ +struct uic_command *uic_cmd; +static const char *const action[] = { +"dme-set" ,"dme-peer-set" + }; +const char *set = action[!!peer]; +unsigned long flags; +int ret; + +if (!ufshcd_ready_uic_cmd (hba)) +return -EIO ; + +spin_lock_irqsave (hba->host->host_lock, flags); + +/* form UIC command */ + uic_cmd = &hba->active_uic_cmd; + uic_cmd->command = peer ? +UIC_CMD_DME_PEER_SET :UIC_CMD_DME_SET ; + uic_cmd->argument1 = attr_sel; + uic_cmd->argument2 =UIC_ARG_ATTR_SET (attr_set); + uic_cmd->argument3 = mib_val; + +/* dispatch UIC commands to controller */ +ufshcd_dispatch_uic_cmd (hba, uic_cmd); +spin_unlock_irqrestore (hba->host->host_lock, flags); + + ret =ufshcd_wait_for_uic_cmd (hba); +dev_dbg (hba->dev,"%s: error code %d returned\n" , set, ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_xxx_set); + +/** +* ufshcd_dme_xxx_get - UIC command for DME_GET, DME_PEER_GET +* @hba: per adapter instance +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_xxx_get (struct ufs_hba *hba,u32 attr_sel,u32 *mib_val,u8 peer) +{ +struct uic_command *uic_cmd; +static const char *const action[] = { +"dme-get" ,"dme-peer-get" + }; +const char *get = action[!!peer]; +unsigned long flags; +int ret; + +if (!ufshcd_ready_uic_cmd (hba)) +return -EIO ; + +spin_lock_irqsave (hba->host->host_lock, flags); + +/* form UIC command */ + uic_cmd = &hba->active_uic_cmd; + uic_cmd->command = peer ? +UIC_CMD_DME_PEER_GET :UIC_CMD_DME_GET ; + uic_cmd->argument1 = attr_sel; + uic_cmd->argument2 =0 ; + uic_cmd->argument3 =0 ; + +/* dispatch UIC commands to controller */ +ufshcd_dispatch_uic_cmd (hba, uic_cmd); +spin_unlock_irqrestore (hba->host->host_lock, flags); + + ret =ufshcd_wait_for_uic_cmd (hba); +if (mib_val) + *mib_val =ufshcd_get_dme_attr_val (hba); + +dev_dbg (hba->dev,"%s: error code %d returned\n" , get, ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_xxx_get); + +/** +* ufshcd_dme_power_xxx - UIC command for DME_POWERON, DME_POWEROFF +* @hba: per adapter instance +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_power_xxx (struct ufs_hba *hba,u8 on) +{ +struct uic_command *uic_cmd; +static const char *const action[] = { +"dme-power-on" , +"dme-power-off" , + }; +const char *power = action[!!on]; +unsigned long flags; +int ret; + +if (!ufshcd_ready_uic_cmd (hba)) +return -EIO ; + +spin_lock_irqsave (hba->host->host_lock, flags); + +/* form UIC command */ + uic_cmd = &hba->active_uic_cmd; + uic_cmd->command = on ? +UIC_CMD_DME_POWERON :UIC_CMD_DME_POWEROFF ; + uic_cmd->argument1 =0 ; + uic_cmd->argument2 =0 ; + uic_cmd->argument3 =0 ; + +/* dispatch UIC commands to controller */ +ufshcd_dispatch_uic_cmd (hba, uic_cmd); + +spin_unlock_irqrestore (hba->host->host_lock, flags); + + ret =ufshcd_wait_for_uic_cmd (hba); +if (ret) +dev_err (hba->dev,"%s: error code %d returned\n" , power, ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_power_xxx); + +/** +* ufshcd_dme_hibern8_xxx - UIC command for DME_HIBERNATE_ENTER, +* DME_HIBERNATE_EXIT +* @hba: per adapter instance +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_hibern8_xxx (struct ufs_hba *hba,u8 enter) +{ +struct uic_command *uic_cmd; +static const char *const action[] = { +"dme-hibernate-enter" , +"dme-hibernate-exit" + }; +const char *hibern8 = action[!!enter]; +unsigned long flags; +u8 status; +int ret; + +if (!ufshcd_ready_uic_cmd (hba)) +return -EIO ; + +spin_lock_irqsave (hba->host->host_lock, flags); + +/* form UIC command */ + uic_cmd = &hba->active_uic_cmd; + uic_cmd->command = enter ? +UIC_CMD_DME_HIBER_ENTER :UIC_CMD_DME_HIBER_EXIT ; + uic_cmd->argument1 =0 ; + uic_cmd->argument2 =0 ; + uic_cmd->argument3 =0 ; + +/* dispatch UIC commands to controller */ +ufshcd_dispatch_uic_cmd (hba, uic_cmd); + +spin_unlock_irqrestore (hba->host->host_lock, flags); + + ret=ufshcd_wait_for_uic_cmd (hba); +if (ret) { +dev_err (hba->dev,"%s: error code %d returned\n" , hibern8, ret); + goto out; + } + +init_completion (&hba->hibern8_done); + +if (wait_for_completion_timeout (&hba->hibern8_done, +msecs_to_jiffies (UIC_CMD_TIMEOUT ))) { + status =ufshcd_get_upmcrs (hba); +if (status !=PWR_LOCAL ) { +dev_err (hba->dev,"%s: failed, host upmcrs:%x\n" , + hibern8, status); + ret = status; + } + }else { +dev_err (hba->dev,"%s: timeout\n" , hibern8); + ret = -ETIMEDOUT ; + } +out: +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_hibern8_xxx); + +/** * ufshcd_make_hba_operational - Make UFS controller operational * @hba: per adapter instance * @@ -1238,6 +1453,9 @@ static void ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status) {if (intr_status &UIC_COMMAND_COMPL )complete (&hba->active_uic_cmd.done); + +if (intr_status &UFSHCD_HIBERNATE_MASK ) +complete (&hba->hibern8_done); }/** @@ -1362,7 +1580,7 @@ static void ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status)if (hba->errors)ufshcd_err_handler (hba); -if (intr_status &UIC_COMMAND_COMPL ) +if (intr_status &UFSHCD_UIC_MASK )ufshcd_uic_cmd_compl (hba, intr_status);if (intr_status &UTP_TASK_REQ_COMPL )drivers/scsi/ufs/ufshcd.h +55
-0@@ -140,6 +140,7 @@ struct ufshcd_lrb {* @active_uic_cmd: handle of active UIC command * @ufshcd_tm_wait_queue: wait queue for task management * @tm_condition: condition variable for task management +* @hibern8_done: completion for hibernate * @ufshcd_state: UFSHCD states * @intr_mask: Interrupt Mask Bits * @link_startup_wq: Work queue for link start-up @@ -177,6 +178,8 @@ struct ufs_hba {wait_queue_head_t ufshcd_tm_wait_queue;unsigned long tm_condition; +struct completion hibern8_done; +u32 ufshcd_state;u32 intr_mask;@@ -197,4 +200,56 @@ void ufshcd_remove(struct ufs_hba *);#define ufshcd_readl (hba, reg) \ readl((hba)->mmio_base + (reg)) + +extern int ufshcd_dme_xxx_set (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val,u8 peer); +extern int ufshcd_dme_xxx_get (struct ufs_hba *hba,u32 attr_sel, +u32 *mib_val,u8 peer); +extern int ufshcd_dme_power_xxx (struct ufs_hba *hba,u8 on); +extern int ufshcd_dme_hibern8_xxx (struct ufs_hba *hba,u8 enter); + +static inline int ufshcd_dme_set (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val) +{ +return ufshcd_dme_xxx_set (hba, attr_sel, attr_set, mib_val,0 ); +} + +static inline int ufshcd_dme_peer_set (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val) +{ +return ufshcd_dme_xxx_set (hba, attr_sel, attr_set, mib_val,1 ); +} + +static inline int ufshcd_dme_get (struct ufs_hba *hba,u32 attr_sel, +u32 *mib_val) +{ +return ufshcd_dme_xxx_get (hba, attr_sel, mib_val,0 ); +} + +static inline int ufshcd_dme_peer_get (struct ufs_hba *hba,u32 attr_sel, +u32 *mib_val) +{ +return ufshcd_dme_xxx_get (hba, attr_sel, mib_val,1 ); +} + +static inline int ufshcd_dme_power_on (struct ufs_hba *hba) +{ +return ufshcd_dme_power_xxx (hba,1 ); +} + +static inline int ufshcd_dme_power_off (struct ufs_hba *hba) +{ +return ufshcd_dme_power_xxx (hba,0 ); +} + +static inline int ufshcd_dme_hibern8_enter (struct ufs_hba *hba,u8 enter) +{ +return ufshcd_dme_hibern8_xxx (hba,1 ); +} + +static inline int ufshcd_dme_hibern8_exit (struct ufs_hba *hba,u8 enter) +{ +return ufshcd_dme_hibern8_xxx (hba,0 ); +} +#endif /* End of Header */ drivers/scsi/ufs/ufshci.h +19
-0@@ -124,6 +124,12 @@ enum {#define CONTROLLER_FATAL_ERROR UFS_BIT(16)#define SYSTEM_BUS_FATAL_ERROR UFS_BIT(17) +#define UFSHCD_HIBERNATE_MASK (UIC_HIBERNATE_ENTER |\ + UIC_HIBERNATE_EXIT) + +#define UFSHCD_UIC_MASK (UIC_COMMAND_COMPL |\ + UFSHCD_HIBERNATE_MASK) +#define UFSHCD_ERROR_MASK (UIC_ERROR |\ DEVICE_FATAL_ERROR |\ CONTROLLER_FATAL_ERROR |\@@ -142,6 +148,15 @@ enum {#define DEVICE_ERROR_INDICATOR UFS_BIT(5)#define UIC_POWER_MODE_CHANGE_REQ_STATUS_MASK UFS_MASK(0x7, 8) +enum { +PWR_OK =0x0 , +PWR_LOCAL =0x01 , +PWR_REMOTE =0x02 , +PWR_BUSY =0x03 , +PWR_ERROR_CAP =0x04 , +PWR_FATAL_ERROR =0x05 , +}; +/* HCE - Host Controller Enable 34h */ #define CONTROLLER_ENABLE UFS_BIT(0)#define CONTROLLER_DISABLE 0x0@@ -191,6 +206,10 @@ enum {#define CONFIG_RESULT_CODE_MASK 0xFF#define GENERIC_ERROR_CODE_MASK 0xFF +#define UIC_ARG_MIB_SEL (attr, sel) (((attr & 0xFFFF) << 16) |\ + (sel & 0xFFFF)) +#define UIC_ARG_ATTR_SET (type) ((type & 0xFF) << 16) +/* UIC Commands */ enum {UIC_CMD_DME_GET =0x01 ,
Quoted 27 lines · Subhash Jadavani
Quoted 26 lines · Seungwon Jeon
Add uic command operations including
DME_XXXseries.Signed-off-by Seungwon Jeon <[email protected]>--- drivers/scsi/ufs/ufs-attrs.h | 129 ++++++++++++++++++++++++ drivers/scsi/ufs/ufshcd.c | 220 +++++++++++++++++++++++++++++++++++++++++- drivers/scsi/ufs/ufshcd.h | 55 +++++++++++ drivers/scsi/ufs/ufshci.h | 19 ++++ 4 files changed, 422 insertions(+), 1 deletions(-)create mode 100644
drivers/scsi/ufs/ufs-attrs.hdrivers/scsi/ufs/ufs-attrs.h new file +9
-0@@ -0,0 +1,129 @@ +/* +* drivers/scsi/ufs/ufs-attrs.h +* +* Copyright (C) 2013 Samsung Electronics Co., Ltd. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version.
Quoted 8 lines
drivers/scsi/ufs/ufs-attrs.h line 13
Quoted 4 lines
drivers/scsi/ufs/ufs-attrs.h new file +4
-0+*/ + +#ifndef _UFS_ATTRS_H_ +#define _UFS_ATTRS_H_I don't see a need to add this file as part of this patch as there are no users of the same in this patch. So its better to remove from here and add it as separate patch when their real use arises.
Even though actual usage is not introduced here, dme_get{set} functions are introduced. These attribute's ids will be used as argument of dme_get{set}.
So, I think definitions would be better to be in this patch.
Quoted 132 lines
Quoted 132 lines
drivers/scsi/ufs/ufs-attrs.h new file +116
-0+ +/* +* PHY Adpater attributes +*/ +#define PA_ACTIVETXDATALANES 0x1560 +#define PA_ACTIVERXDATALANES 0x1580 +#define PA_TXTRAILINGCLOCKS 0x1564 +#define PA_PHY_TYPE 0x1500 +#define PA_AVAILTXDATALANES 0x1520 +#define PA_AVAILRXDATALANES 0x1540 +#define PA_MINRXTRAILINGCLOCKS 0x1543 +#define PA_TXPWRSTATUS 0x1567 +#define PA_RXPWRSTATUS 0x1582 +#define PA_TXFORCECLOCK 0x1562 +#define PA_TXPWRMODE 0x1563 +#define PA_LEGACYDPHYESCDL 0x1570 +#define PA_MAXTXSPEEDFAST 0x1521 +#define PA_MAXTXSPEEDSLOW 0x1522 +#define PA_MAXRXSPEEDFAST 0x1541 +#define PA_MAXRXSPEEDSLOW 0x1542 +#define PA_TXLINKSTARTUPHS 0x1544 +#define PA_TXSPEEDFAST 0x1565 +#define PA_TXSPEEDSLOW 0x1566 +#define PA_REMOTEVERINFO 0x15A0 +#define PA_TXGEAR 0x1568 +#define PA_TXTERMINATION 0x1569 +#define PA_HSSERIES 0x156A +#define PA_PWRMODE 0x1571 +#define PA_RXGEAR 0x1583 +#define PA_RXTERMINATION 0x1584 +#define PA_MAXRXPWMGEAR 0x1586 +#define PA_MAXRXHSGEAR 0x1587 +#define PA_RXHSUNTERMCAP 0x15A5 +#define PA_RXLSTERMCAP 0x15A6 +#define PA_PACPREQTIMEOUT 0x1590 +#define PA_PACPREQEOBTIMEOUT 0x1591 +#define PA_LOCALVERINFO 0x15A9 +#define PA_TACTIVATE 0x15A8 +#define PA_PACPFRAMECOUNT 0x15C0 +#define PA_PACPERRORCOUNT 0x15C1 +#define PA_PHYTESTCONTROL 0x15C2 +#define PA_PWRMODEUSERDATA0 0x15B0 +#define PA_PWRMODEUSERDATA1 0x15B1 +#define PA_PWRMODEUSERDATA2 0x15B2 +#define PA_PWRMODEUSERDATA3 0x15B3 +#define PA_PWRMODEUSERDATA4 0x15B4 +#define PA_PWRMODEUSERDATA5 0x15B5 +#define PA_PWRMODEUSERDATA6 0x15B6 +#define PA_PWRMODEUSERDATA7 0x15B7 +#define PA_PWRMODEUSERDATA8 0x15B8 +#define PA_PWRMODEUSERDATA9 0x15B9 +#define PA_PWRMODEUSERDATA10 0x15BA +#define PA_PWRMODEUSERDATA11 0x15BB +#define PA_CONNECTEDTXDATALANE 0x1561 +#define PA_CONNECTEDRXDATALANE 0x1581 +#define PA_LOGICALLANEMAP 0x15A1 +#define PA_SLEEPNOCONFIGTIME 0x15A2 +#define PA_STALLNOCONFIGTIME 0x15A3 +#define PA_SAVECONFIGTIME 0x15A4 + +/* +* Data Link Layer Attributes +*/ +#define DL_TC0TXFCTHRESHOLD 0x2040 +#define DL_FC0PROTTIMEOUTVAL 0x2041 +#define DL_TC0REPLAYTIMEOUTVAL 0x2042 +#define DL_AFC0REQTIMEOUTVAL 0x2043 +#define DL_AFC0CREDITTHRESHOLD 0x2044 +#define DL_TC0OUTACKTHRESHOLD 0x2045 +#define DL_TC1TXFCTHRESHOLD 0x2060 +#define DL_FC1PROTTIMEOUTVAL 0x2061 +#define DL_TC1REPLAYTIMEOUTVAL 0x2062 +#define DL_AFC1REQTIMEOUTVAL 0x2063 +#define DL_AFC1CREDITTHRESHOLD 0x2064 +#define DL_TC1OUTACKTHRESHOLD 0x2065 +#define DL_TXPREEMPTIONCAP 0x2000 +#define DL_TC0TXMAXSDUSIZE 0x2001 +#define DL_TC0RXINITCREDITVAL 0x2002 +#define DL_TC0TXBUFFERSIZE 0x2005 +#define DL_PEERTC0PRESENT 0x2046 +#define DL_PEERTC0RXINITCREVAL 0x2047 +#define DL_TC1TXMAXSDUSIZE 0x2003 +#define DL_TC1RXINITCREDITVAL 0x2004 +#define DL_TC1TXBUFFERSIZE 0x2006 +#define DL_PEERTC1PRESENT 0x2066 +#define DL_PEERTC1RXINITCREVAL 0x2067 + +/* +* Network Layer Attributes +*/ +#define N_DEVICEID 0x3000 +#define N_DEVICEID_VALID 0x3001 +#define N_TC0TXMAXSDUSIZE 0x3020 +#define N_TC1TXMAXSDUSIZE 0x3021 + +/* +* Transport Layer Attributes +*/ +#define T_NUMCPORTS 0x4000 +#define T_NUMTESTFEATURES 0x4001 +#define T_CONNECTIONSTATE 0x4020 +#define T_PEERDEVICEID 0x4021 +#define T_PEERCPORTID 0x4022 +#define T_TRAFFICCLASS 0x4023 +#define T_PROTOCOLID 0x4024 +#define T_CPORTFLAGS 0x4025 +#define T_TXTOKENVALUE 0x4026 +#define T_RXTOKENVALUE 0x4027 +#define T_LOCALBUFFERSPACE 0x4028 +#define T_PEERBUFFERSPACE 0x4029 +#define T_CREDITSTOSEND 0x402A +#define T_CPORTMODE 0x402B +#define T_TC0TXMAXSDUSIZE 0x4060 +#define T_TC1TXMAXSDUSIZE 0x4061 + +#endif /* _UFS_ATTRS_H_ */ drivers/scsi/ufs/ufshcd.c +1
-0@@ -37,6 +37,7 @@#define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\ UTP_TASK_REQ_COMPL |\ + UFSHCD_HIBERNATE_MASK |\ UFSHCD_ERROR_MASK)#define UIC_CMD_TIMEOUT 100@@ -188,6 +189,31 @@ static inline int ufshcd_get_uic_cmd_result(struct ufs_hba *hba) }
Quoted 15 lines
drivers/scsi/ufs/ufshcd.c static inline int ufshcd_get_uic_cmd_result(struct ufs_hba *hba) · line 203
Quoted 13 lines
drivers/scsi/ufs/ufshcd.c +12
-0/** +* ufshcd_get_dme_attr_val - Get the value of attribute returned by UIC command +* @hba: Pointer to adapter instance +* +* This function gets UIC command argument3 +* Returns 0 on success, non zero value on error +*/ +static inline u32 ufshcd_get_dme_attr_val (struct ufs_hba *hba) +{ +return ufshcd_readl (hba,REG_UIC_COMMAND_ARG_3 ); +} + +Please remove one extra line space above.
Ok.
Quoted 359 lines
Quoted 344 lines
drivers/scsi/ufs/ufshcd.c +206
-1+/** +* ufshcd_get_upmcrs - Get the power mode change request status +* @hba: Pointer to adapter instance +* +* This function gets the UPMCRS field of HCS register +* Returns value of UPMCRS field +*/ +static inline u8 ufshcd_get_upmcrs (struct ufs_hba *hba) +{ +return (ufshcd_readl (hba,REG_CONTROLLER_STATUS ) >>8 ) &0x7 ; +} + +/** * ufshcd_free_hba_memory - Free allocated memory for LRB, request * and task lists * @hba: Pointer to adapter instance @@ -804,6 +830,195 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba) }/** +* ufshcd_dme_xxx_set - UIC command for DME_SET, DME_PEER_SET +* @hba: per adapter instance +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_xxx_set (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val,u8 peer) +{ +struct uic_command *uic_cmd; +static const char *const action[] = { +"dme-set" ,"dme-peer-set" + }; +const char *set = action[!!peer]; +unsigned long flags; +int ret; + +if (!ufshcd_ready_uic_cmd (hba)) +return -EIO ; + +spin_lock_irqsave (hba->host->host_lock, flags); + +/* form UIC command */ + uic_cmd = &hba->active_uic_cmd; + uic_cmd->command = peer ? +UIC_CMD_DME_PEER_SET :UIC_CMD_DME_SET ; + uic_cmd->argument1 = attr_sel; + uic_cmd->argument2 =UIC_ARG_ATTR_SET (attr_set); + uic_cmd->argument3 = mib_val; + +/* dispatch UIC commands to controller */ +ufshcd_dispatch_uic_cmd (hba, uic_cmd); +spin_unlock_irqrestore (hba->host->host_lock, flags); + + ret =ufshcd_wait_for_uic_cmd (hba); +dev_dbg (hba->dev,"%s: error code %d returned\n" , set, ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_xxx_set); + +/** +* ufshcd_dme_xxx_get - UIC command for DME_GET, DME_PEER_GET +* @hba: per adapter instance +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_xxx_get (struct ufs_hba *hba,u32 attr_sel,u32 *mib_val,u8 peer) +{ +struct uic_command *uic_cmd; +static const char *const action[] = { +"dme-get" ,"dme-peer-get" + }; +const char *get = action[!!peer]; +unsigned long flags; +int ret; + +if (!ufshcd_ready_uic_cmd (hba)) +return -EIO ; + +spin_lock_irqsave (hba->host->host_lock, flags); + +/* form UIC command */ + uic_cmd = &hba->active_uic_cmd; + uic_cmd->command = peer ? +UIC_CMD_DME_PEER_GET :UIC_CMD_DME_GET ; + uic_cmd->argument1 = attr_sel; + uic_cmd->argument2 =0 ; + uic_cmd->argument3 =0 ; + +/* dispatch UIC commands to controller */ +ufshcd_dispatch_uic_cmd (hba, uic_cmd); +spin_unlock_irqrestore (hba->host->host_lock, flags); + + ret =ufshcd_wait_for_uic_cmd (hba); +if (mib_val) + *mib_val =ufshcd_get_dme_attr_val (hba); + +dev_dbg (hba->dev,"%s: error code %d returned\n" , get, ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_xxx_get); + +/** +* ufshcd_dme_power_xxx - UIC command for DME_POWERON, DME_POWEROFF +* @hba: per adapter instance +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_power_xxx (struct ufs_hba *hba,u8 on) +{ +struct uic_command *uic_cmd; +static const char *const action[] = { +"dme-power-on" , +"dme-power-off" , + }; +const char *power = action[!!on]; +unsigned long flags; +int ret; + +if (!ufshcd_ready_uic_cmd (hba)) +return -EIO ; + +spin_lock_irqsave (hba->host->host_lock, flags); + +/* form UIC command */ + uic_cmd = &hba->active_uic_cmd; + uic_cmd->command = on ? +UIC_CMD_DME_POWERON :UIC_CMD_DME_POWEROFF ; + uic_cmd->argument1 =0 ; + uic_cmd->argument2 =0 ; + uic_cmd->argument3 =0 ; + +/* dispatch UIC commands to controller */ +ufshcd_dispatch_uic_cmd (hba, uic_cmd); + +spin_unlock_irqrestore (hba->host->host_lock, flags); + + ret =ufshcd_wait_for_uic_cmd (hba); +if (ret) +dev_err (hba->dev,"%s: error code %d returned\n" , power, ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_power_xxx); + +/** +* ufshcd_dme_hibern8_xxx - UIC command for DME_HIBERNATE_ENTER, +* DME_HIBERNATE_EXIT +* @hba: per adapter instance +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_hibern8_xxx (struct ufs_hba *hba,u8 enter) +{ +struct uic_command *uic_cmd; +static const char *const action[] = { +"dme-hibernate-enter" , +"dme-hibernate-exit" + }; +const char *hibern8 = action[!!enter]; +unsigned long flags; +u8 status; +int ret; + +if (!ufshcd_ready_uic_cmd (hba)) +return -EIO ; + +spin_lock_irqsave (hba->host->host_lock, flags); + +/* form UIC command */ + uic_cmd = &hba->active_uic_cmd; + uic_cmd->command = enter ? +UIC_CMD_DME_HIBER_ENTER :UIC_CMD_DME_HIBER_EXIT ; + uic_cmd->argument1 =0 ; + uic_cmd->argument2 =0 ; + uic_cmd->argument3 =0 ; + +/* dispatch UIC commands to controller */ +ufshcd_dispatch_uic_cmd (hba, uic_cmd); + +spin_unlock_irqrestore (hba->host->host_lock, flags); + + ret=ufshcd_wait_for_uic_cmd (hba); +if (ret) { +dev_err (hba->dev,"%s: error code %d returned\n" , hibern8, ret); + goto out; + } + +init_completion (&hba->hibern8_done); + +if (wait_for_completion_timeout (&hba->hibern8_done, +msecs_to_jiffies (UIC_CMD_TIMEOUT ))) { + status =ufshcd_get_upmcrs (hba); +if (status !=PWR_LOCAL ) { +dev_err (hba->dev,"%s: failed, host upmcrs:%x\n" , + hibern8, status); + ret = status; + } + }else { +dev_err (hba->dev,"%s: timeout\n" , hibern8); + ret = -ETIMEDOUT ; + } +out: +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_hibern8_xxx); + +/** * ufshcd_make_hba_operational - Make UFS controller operational * @hba: per adapter instance * @@ -1238,6 +1453,9 @@ static void ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status) {if (intr_status &UIC_COMMAND_COMPL )complete (&hba->active_uic_cmd.done); + +if (intr_status &UFSHCD_HIBERNATE_MASK ) +complete (&hba->hibern8_done); }/** @@ -1362,7 +1580,7 @@ static void ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status)if (hba->errors)ufshcd_err_handler (hba); -if (intr_status &UIC_COMMAND_COMPL ) +if (intr_status &UFSHCD_UIC_MASK )ufshcd_uic_cmd_compl (hba, intr_status);if (intr_status &UTP_TASK_REQ_COMPL )drivers/scsi/ufs/ufshcd.h +55
-0@@ -140,6 +140,7 @@ struct ufshcd_lrb {* @active_uic_cmd: handle of active UIC command * @ufshcd_tm_wait_queue: wait queue for task management * @tm_condition: condition variable for task management +* @hibern8_done: completion for hibernate * @ufshcd_state: UFSHCD states * @intr_mask: Interrupt Mask Bits * @link_startup_wq: Work queue for link start-up @@ -177,6 +178,8 @@ struct ufs_hba {wait_queue_head_t ufshcd_tm_wait_queue;unsigned long tm_condition; +struct completion hibern8_done; +u32 ufshcd_state;u32 intr_mask;@@ -197,4 +200,56 @@ void ufshcd_remove(struct ufs_hba *);#define ufshcd_readl (hba, reg) \ readl((hba)->mmio_base + (reg)) + +extern int ufshcd_dme_xxx_set (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val,u8 peer); +extern int ufshcd_dme_xxx_get (struct ufs_hba *hba,u32 attr_sel, +u32 *mib_val,u8 peer); +extern int ufshcd_dme_power_xxx (struct ufs_hba *hba,u8 on); +extern int ufshcd_dme_hibern8_xxx (struct ufs_hba *hba,u8 enter); + +static inline int ufshcd_dme_set (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val) +{ +return ufshcd_dme_xxx_set (hba, attr_sel, attr_set, mib_val,0 ); +} + +static inline int ufshcd_dme_peer_set (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val) +{ +return ufshcd_dme_xxx_set (hba, attr_sel, attr_set, mib_val,1 ); +} + +static inline int ufshcd_dme_get (struct ufs_hba *hba,u32 attr_sel, +u32 *mib_val) +{ +return ufshcd_dme_xxx_get (hba, attr_sel, mib_val,0 ); +} + +static inline int ufshcd_dme_peer_get (struct ufs_hba *hba,u32 attr_sel, +u32 *mib_val) +{ +return ufshcd_dme_xxx_get (hba, attr_sel, mib_val,1 ); +} + +static inline int ufshcd_dme_power_on (struct ufs_hba *hba) +{ +return ufshcd_dme_power_xxx (hba,1 ); +} + +static inline int ufshcd_dme_power_off (struct ufs_hba *hba) +{ +return ufshcd_dme_power_xxx (hba,0 ); +} + +static inline int ufshcd_dme_hibern8_enter (struct ufs_hba *hba,u8 enter) +{ +return ufshcd_dme_hibern8_xxx (hba,1 ); +} + +static inline int ufshcd_dme_hibern8_exit (struct ufs_hba *hba,u8 enter) +{ +return ufshcd_dme_hibern8_xxx (hba,0 ); +} +#endif /* End of Header */ drivers/scsi/ufs/ufshci.h +15
-0@@ -124,6 +124,12 @@ enum {#define CONTROLLER_FATAL_ERROR UFS_BIT(16)#define SYSTEM_BUS_FATAL_ERROR UFS_BIT(17) +#define UFSHCD_HIBERNATE_MASK (UIC_HIBERNATE_ENTER |\ + UIC_HIBERNATE_EXIT) + +#define UFSHCD_UIC_MASK (UIC_COMMAND_COMPL |\ + UFSHCD_HIBERNATE_MASK) +#define UFSHCD_ERROR_MASK (UIC_ERROR |\ DEVICE_FATAL_ERROR |\ CONTROLLER_FATAL_ERROR |\@@ -142,6 +148,15 @@ enum {#define DEVICE_ERROR_INDICATOR UFS_BIT(5)#define UIC_POWER_MODE_CHANGE_REQ_STATUS_MASK UFS_MASK(0x7, 8) +enum { +PWR_OK =0x0 , +PWR_LOCAL =0x01 , +PWR_REMOTE =0x02 , +PWR_BUSY =0x03 , +PWR_ERROR_CAP =0x04 , +PWR_FATAL_ERROR =0x05 , +}; +/* HCE - Host Controller Enable 34h */ #define CONTROLLER_ENABLE UFS_BIT(0)#define CONTROLLER_DISABLE 0x0drivers/scsi/ufs/ufshci.h enum { · line 215
Quoted 10 lines
drivers/scsi/ufs/ufshci.h +4
-0@@ -191,6 +206,10 @@ enum {#define CONFIG_RESULT_CODE_MASK 0xFF#define GENERIC_ERROR_CODE_MASK 0xFF +#define UIC_ARG_MIB_SEL (attr, sel) (((attr & 0xFFFF) << 16) |\ + (sel & 0xFFFF)) +#define UIC_ARG_ATTR_SET (type) ((type & 0xFF) << 16) +/* UIC Commands */ enum {UIC_CMD_DME_GET =0x01 ,--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH v2 5/7 scsi: ufs: rework link start-up process
In reply to Seungwon JeonLink start-up requires long time with multiphase handshakes between UFS host and device. This affects driver's probe time. This patch let link start-up run asynchronously. Link start-up will be executed at the end of prove separately. Along with this change, the following is worked.
Defined completion time of uic command to avoid a permanent wait. Added mutex to guarantee of uic command at a time. Adapted some sequence of controller initialization after link statup according to HCI standard.
--- drivers/scsi/ufs/ufshcd.c | 287 ++++++++++++++++++++++++++++++--------------- drivers/scsi/ufs/ufshcd.h | 10 +- 2 files changed, 200 insertions(+), 97 deletions(-)
drivers/scsi/ufs/ufshcd.c +193 -94
@@ -33,11 +33,15 @@* this program. */ +#include <linux/async.h> +#include "ufshcd.h" #define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\ UTP_TASK_REQ_COMPL |\ UFSHCD_ERROR_MASK) +/* UIC command timeout, unit: ms */ +#define UIC_CMD_TIMEOUT 500enum {UFSHCD_MAX_CHANNEL =0 ,
@@ -410,24 +414,115 @@ static inline void ufshcd_hba_capabilities(struct ufs_hba *hba) }/** -* ufshcd_send_uic_command - Send UIC commands to unipro layers +* ufshcd_ready_for_uic_cmd - Check if controller is ready +* to accept UIC commands * @hba: per adapter instance -* @uic_command: UIC command +* Return true on success, else false +*/ +static inline bool ufshcd_ready_for_uic_cmd (struct ufs_hba *hba) +{ +if (ufshcd_readl (hba,REG_CONTROLLER_STATUS ) &UIC_COMMAND_READY ) +return true; +else +return false; +} + +/** +* ufshcd_dispatch_uic_cmd - Dispatch UIC commands to unipro layers +* @hba: per adapter instance +* @uic_cmd: UIC command +* +* Mutex must be held. */ static inline void -ufshcd_send_uic_command (struct ufs_hba *hba,struct uic_command *uic_cmnd) +ufshcd_dispatch_uic_cmd (struct ufs_hba *hba,struct uic_command *uic_cmd) { + hba->active_uic_cmd = uic_cmd; +/* Write Args */ -ufshcd_writel (hba, uic_cmnd->argument1,REG_UIC_COMMAND_ARG_1 ); -ufshcd_writel (hba, uic_cmnd->argument2,REG_UIC_COMMAND_ARG_2 ); -ufshcd_writel (hba, uic_cmnd->argument3,REG_UIC_COMMAND_ARG_3 ); +ufshcd_writel (hba, uic_cmd->argument1,REG_UIC_COMMAND_ARG_1 ); +ufshcd_writel (hba, uic_cmd->argument2,REG_UIC_COMMAND_ARG_2 ); +ufshcd_writel (hba, uic_cmd->argument3,REG_UIC_COMMAND_ARG_3 );/* Write UIC Cmd */ -ufshcd_writel (hba, uic_cmnd->command &COMMAND_OPCODE_MASK , +ufshcd_writel (hba, uic_cmd->command &COMMAND_OPCODE_MASK ,REG_UIC_COMMAND ); }/** +* ufshcd_wait_for_uic_cmd - Wait complectioin of UIC command +* @hba: per adapter instance +* @uic_command: UIC command +* +* Must be called with mutex held. +* Returns 0 only if success. +*/ +static int +ufshcd_wait_for_uic_cmd (struct ufs_hba *hba,struct uic_command *uic_cmd) +{ +int ret; + +if (wait_for_completion_timeout (&uic_cmd->done, +msecs_to_jiffies (UIC_CMD_TIMEOUT ))) + ret = uic_cmd->argument2 &MASK_UIC_COMMAND_RESULT ; +else + ret = -ETIMEDOUT ; + +return ret; +} + +/** +* __ufshcd_send_uic_cmd - Send UIC commands and retrieve the result +* @hba: per adapter instance +* @uic_cmd: UIC command +* +* Identical to ufshcd_send_uic_cmd() expect mutex. Must be called +* with mutex held. +* Returns 0 only if success. +*/ +static int +__ufshcd_send_uic_cmd (struct ufs_hba *hba,struct uic_command *uic_cmd) +{ +int ret; +unsigned long flags; + +if (!ufshcd_ready_for_uic_cmd (hba)) { +dev_err (hba->dev, +"Controller not ready to accept UIC commands\n" ); +return -EIO ; + } + +init_completion (&uic_cmd->done); + +spin_lock_irqsave (hba->host->host_lock, flags); +ufshcd_dispatch_uic_cmd (hba, uic_cmd); +spin_unlock_irqrestore (hba->host->host_lock, flags); + + ret =ufshcd_wait_for_uic_cmd (hba, uic_cmd); + +return ret; +} + +/** +* ufshcd_send_uic_cmd - Send UIC commands and retrieve the result +* @hba: per adapter instance +* @uic_cmd: UIC command +* +* Returns 0 only if success. +*/ +static int +ufshcd_send_uic_cmd (struct ufs_hba *hba,struct uic_command *uic_cmd) +{ +int ret; + +mutex_lock (&hba->uic_cmd_mutex); + ret =__ufshcd_send_uic_cmd (hba, uic_cmd); +mutex_unlock (&hba->uic_cmd_mutex); + +return ret; +} + +/** * ufshcd_map_sg - Map scatter-gather list to prdt * @lrbp - pointer to local reference block *
@@ -971,34 +1066,16 @@ static void ufshcd_host_memory_configure(struct ufs_hba *hba)*/ static int ufshcd_dme_link_startup (struct ufs_hba *hba) { -struct uic_command *uic_cmd; -unsigned long flags; +struct uic_command uic_cmd = {0 }; +int ret; -/* check if controller is ready to accept UIC commands */ -if ((ufshcd_readl (hba,REG_CONTROLLER_STATUS ) & -UIC_COMMAND_READY ) ==0x0 ) { -dev_err (hba->dev, -"Controller not ready" -" to accept UIC commands\n" ); -return -EIO ; - } - -spin_lock_irqsave (hba->host->host_lock, flags); + uic_cmd.command =UIC_CMD_DME_LINK_STARTUP ; -/* form UIC command */ - uic_cmd = &hba->active_uic_cmd; - uic_cmd->command =UIC_CMD_DME_LINK_STARTUP ; - uic_cmd->argument1 =0 ; - uic_cmd->argument2 =0 ; - uic_cmd->argument3 =0 ; - -/* enable UIC related interrupts */ -ufshcd_enable_intr (hba,UIC_COMMAND_COMPL ); - -/* sending UIC commands to controller */ -ufshcd_send_uic_command (hba, uic_cmd); -spin_unlock_irqrestore (hba->host->host_lock, flags); -return 0 ; + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) +dev_err (hba->dev, +"link startup: error code %d\n" , ret); +return ret; }/**
@@ -1007,9 +1084,10 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba)* * To bring UFS host controller to operational state, * 1. Check if device is present -* 2. Configure run-stop-registers -* 3. Enable required interrupts -* 4. Configure interrupt aggregation +* 2. Enable required interrupts +* 3. Configure interrupt aggregation +* 4. Program UTRL and UTMRL base addres +* 5. Configure run-stop-registers * * Returns 0 on success, non-zero value on failure */
@@ -1026,6 +1104,22 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba) goto out; } +/* Enable required interrupts */ +ufshcd_enable_intr (hba,UFSHCD_ENABLE_INTRS ); + +/* Configure interrupt aggregation */ +ufshcd_config_int_aggr (hba,INT_AGGR_CONFIG ); + +/* Configure UTRL and UTMRL base address registers */ +ufshcd_writel (hba,lower_32_bits (hba->utrdl_dma_addr), +REG_UTP_TRANSFER_REQ_LIST_BASE_L ); +ufshcd_writel (hba,upper_32_bits (hba->utrdl_dma_addr), +REG_UTP_TRANSFER_REQ_LIST_BASE_H ); +ufshcd_writel (hba,lower_32_bits (hba->utmrdl_dma_addr), +REG_UTP_TASK_REQ_LIST_BASE_L ); +ufshcd_writel (hba,upper_32_bits (hba->utmrdl_dma_addr), +REG_UTP_TASK_REQ_LIST_BASE_H ); +/* * UCRDY, UTMRLDY and UTRLRDY bits must be 1 * DEI, HEI bits must be 0
@@ -1039,17 +1133,11 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba) goto out; } -/* Enable required interrupts */ -ufshcd_enable_intr (hba,UFSHCD_ENABLE_INTRS ); - -/* Configure interrupt aggregation */ -ufshcd_config_int_aggr (hba,INT_AGGR_CONFIG ); -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 err; }
@@ -1118,34 +1206,29 @@ static int ufshcd_hba_enable(struct ufs_hba *hba) }/** -* ufshcd_initialize_hba - start the initialization process +* ufshcd_link_startup - Initialize unipro link startup * @hba: per adapter instance * -* 1. Enable the controller via ufshcd_hba_enable. -* 2. Program the Transfer Request List Address with the starting address of -* UTRDL. -* 3. Program the Task Management Request List Address with starting address -* of UTMRDL. -* -* Returns 0 on success, non-zero value on failure. +* Returns 0 for success, non-zero in case of failure */ -static int ufshcd_initialize_hba (struct ufs_hba *hba) +static int ufshcd_link_startup (struct ufs_hba *hba) { -if (ufshcd_hba_enable (hba)) -return -EIO ; +int ret; -/* Configure UTRL and UTMRL base address registers */ -ufshcd_writel (hba,lower_32_bits (hba->utrdl_dma_addr), -REG_UTP_TRANSFER_REQ_LIST_BASE_L ); -ufshcd_writel (hba,upper_32_bits (hba->utrdl_dma_addr), -REG_UTP_TRANSFER_REQ_LIST_BASE_H ); -ufshcd_writel (hba,lower_32_bits (hba->utmrdl_dma_addr), -REG_UTP_TASK_REQ_LIST_BASE_L ); -ufshcd_writel (hba,upper_32_bits (hba->utmrdl_dma_addr), -REG_UTP_TASK_REQ_LIST_BASE_H ); +/* enable UIC related interrupts */ +ufshcd_enable_intr (hba,UIC_COMMAND_COMPL ); + + ret =ufshcd_dme_link_startup (hba); +if (ret) + goto out; -/* Initialize unipro link startup procedure */ -return ufshcd_dme_link_startup (hba); + ret =ufshcd_make_hba_operational (hba); +if (ret) + goto out; + +out: +dev_err (hba->dev,"link startup failed %d\n" , ret); +return ret; }/**
@@ -1185,12 +1268,19 @@ static int ufshcd_do_reset(struct ufs_hba *hba) hba->outstanding_reqs =0 ; hba->outstanding_tasks =0 ; -/* start the initialization process */ -if (ufshcd_initialize_hba (hba)) { +/* Host controller enable */ +if (ufshcd_hba_enable (hba)) {dev_err (hba->dev,"Reset: Controller initialization failed\n" );return FAILED ; } + +if (ufshcd_link_startup (hba)) { +dev_err (hba->dev, +"Reset: Link start-up failed\n" ); +return FAILED ; + } +return SUCCESS ; }
@@ -1443,6 +1533,17 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) }/** +* ufshcd_uic_cmd_compl - handle completion of uic command +* @hba: per adapter instance +*/ +static void ufshcd_uic_cmd_compl (struct ufs_hba *hba) +{ + hba->active_uic_cmd->argument2 |= +ufshcd_get_uic_cmd_result (hba); +complete (&hba->active_uic_cmd->done); +} + +/** * ufshcd_transfer_req_compl - handle SCSI and query command completion * @hba: per adapter instance */
@@ -1482,28 +1583,6 @@ static void ufshcd_transfer_req_compl(struct ufs_hba *hba) }/** -* ufshcd_uic_cc_handler - handle UIC command completion -* @work: pointer to a work queue structure -* -* Returns 0 on success, non-zero value on failure -*/ -static void ufshcd_uic_cc_handler (struct work_struct *work) -{ -struct ufs_hba *hba; - - hba = container_of(work, struct ufs_hba, uic_workq); - -if ((hba->active_uic_cmd.command ==UIC_CMD_DME_LINK_STARTUP ) && - !(ufshcd_get_uic_cmd_result (hba))) { - -if (ufshcd_make_hba_operational (hba)) -dev_err (hba->dev, -"cc: hba not operational state\n" ); -return ; - } -} - -/** * ufshcd_fatal_err_handler - handle fatal errors * @hba: per adapter instance */
@@ -1564,7 +1643,7 @@ static void ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status)ufshcd_err_handler (hba);if (intr_status &UIC_COMMAND_COMPL ) -schedule_work (&hba->uic_workq); +ufshcd_uic_cmd_compl (hba);if (intr_status &UTP_TASK_REQ_COMPL )ufshcd_tmc_handler (hba);
@@ -1787,6 +1866,21 @@ out:return err; } +/** +* ufshcd_async_scan - asynchronous execution for link startup +* @data: data pointer to pass to this function +* @cookie: cookie data +*/ +static void ufshcd_async_scan (void *data,async_cookie_t cookie) +{ +struct ufs_hba *hba = (struct ufs_hba *)data; +int ret; + + ret =ufshcd_link_startup (hba); +if (!ret) +scsi_scan_host (hba->host); +} +static struct scsi_host_template ufshcd_driver_template = { .module =THIS_MODULE , .name =UFSHCD ,
@@ -1948,12 +2042,14 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle,init_waitqueue_head (&hba->ufshcd_tm_wait_queue);/* Initialize work queues */ -INIT_WORK (&hba->uic_workq, ufshcd_uic_cc_handler);INIT_WORK (&hba->feh_workq, ufshcd_fatal_err_handler);/* Initialize mutex for query requests */ mutex_init (&hba->query.lock_ufs_query); +/* Initialize UIC command mutex */ +mutex_init (&hba->uic_cmd_mutex); +/* IRQ registration */ err =request_irq (irq, ufshcd_intr,IRQF_SHARED ,UFSHCD , hba);if (err) {
@@ -1974,14 +2070,17 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle, goto out_free_irq; } -/* Initialization routine */ - err =ufshcd_initialize_hba (hba); +/* Host controller enable */ + err =ufshcd_hba_enable (hba);if (err) { -dev_err (hba->dev,"Initialization failed\n" ); +dev_err (hba->dev,"Host controller enable failed\n" ); goto out_remove_scsi_host; } + *hba_handle = hba; +async_schedule (ufshcd_async_scan, hba); +return 0 ; out_remove_scsi_host:
drivers/scsi/ufs/ufshcd.h +7 -3
@@ -51,6 +51,7 @@#include <linux/bitops.h> #include <linux/pm_runtime.h> #include <linux/clk.h> +#include <linux/completion.h> #include <asm/irq.h> #include <asm/byteorder.h>
@@ -76,6 +77,7 @@* @argument3: UIC command argument 3 * @cmd_active: Indicate if UIC command is outstanding * @result: UIC command result +* @done: UIC command completion */ struct uic_command {u32 command;
@@ -84,6 +86,7 @@ struct uic_command {u32 argument3;int cmd_active;int result; +struct completion done; };/**
@@ -150,11 +153,11 @@ struct ufs_query {* @ufs_version: UFS Version to which controller complies * @irq: Irq number of the controller * @active_uic_cmd: handle of active UIC command +* @uic_cmd_mutex: mutex for uic command * @ufshcd_tm_wait_queue: wait queue for task management * @tm_condition: condition variable for task management * @ufshcd_state: UFSHCD states * @intr_mask: Interrupt Mask Bits -* @uic_workq: Work queue for UIC completion handling * @feh_workq: Work queue for fatal controller error handling * @errors: HBA errors * @query: query request information
@@ -186,7 +189,9 @@ struct ufs_hba {u32 ufs_version;unsigned int irq; -struct uic_command active_uic_cmd; +struct uic_command *active_uic_cmd; +struct mutex uic_cmd_mutex; +wait_queue_head_t ufshcd_tm_wait_queue;unsigned long tm_condition;
@@ -194,7 +199,6 @@ struct ufs_hba {u32 intr_mask;/* Work Queues */ -struct work_struct uic_workq;struct work_struct feh_workq;/* HBA Errors */
Signature · 1 line
1.7.0.4
PATCH v2 6/7 scsi: ufs: add dme configuration primitives
In reply to Seungwon JeonImplements to support Get and Set operation of the DME. And along with these operations, IDs of Attribute are added. It is used to configure the behavior of the UNIPRO.
--- drivers/scsi/ufs/ufshcd.c | 84 +++++++++++++++++++++++++++++ drivers/scsi/ufs/ufshcd.h | 29 ++++++++++ drivers/scsi/ufs/ufshci.h | 4 ++ drivers/scsi/ufs/unipro.h | 129 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 246 insertions(+), 0 deletions(-) create mode 100644 drivers/scsi/ufs/unipro.h
drivers/scsi/ufs/ufshcd.c +84 -0
@@ -191,6 +191,18 @@ static inline int ufshcd_get_uic_cmd_result(struct ufs_hba *hba) }/** +* ufshcd_get_dme_attr_val - Get the value of attribute returned by UIC command +* @hba: Pointer to adapter instance +* +* This function gets UIC command argument3 +* Returns 0 on success, non zero value on error +*/ +static inline u32 ufshcd_get_dme_attr_val (struct ufs_hba *hba) +{ +return ufshcd_readl (hba,REG_UIC_COMMAND_ARG_3 ); +} + +/** * ufshcd_free_hba_memory - Free allocated memory for LRB, request * and task lists * @hba: Pointer to adapter instance
@@ -1079,6 +1091,76 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba) }/** +* ufshcd_dme_xxx_set - UIC command for DME_SET, DME_PEER_SET +* @hba: per adapter instance +* @attr_sel: uic command argument1 +* @attr_set: attribute set type as uic command argument2 +* @mib_val: setting value as uic command argument3 +* @peer: indicate wherter peer or non-peer +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_xxx_set (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val,u8 peer) +{ +struct uic_command uic_cmd = {0 }; +static const char *const action[] = { +"dme-set" , +"dme-peer-set" + }; +const char *set = action[!!peer]; +int ret; + + uic_cmd.command = peer ? +UIC_CMD_DME_PEER_SET :UIC_CMD_DME_SET ; + uic_cmd.argument1 = attr_sel; + uic_cmd.argument2 =UIC_ARG_ATTR_SET (attr_set); + uic_cmd.argument3 = mib_val; + + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); + +dev_dbg (hba->dev,"%s: error code %d\n" , set, ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_xxx_set); + +/** +* ufshcd_dme_xxx_get - UIC command for DME_GET, DME_PEER_GET +* @hba: per adapter instance +* @attr_sel: uic command argument1 +* @mib_val: the value of the attribute as returned by the UIC command +* @peer: indicate wherter peer or non-peer +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_xxx_get (struct ufs_hba *hba,u32 attr_sel, +u32 *mib_val,u8 peer) +{ +struct uic_command uic_cmd = {0 }; +static const char *const action[] = { +"dme-get" , +"dme-peer-get" + }; +const char *get = action[!!peer]; +int ret; + + uic_cmd.command = peer ? +UIC_CMD_DME_PEER_GET :UIC_CMD_DME_GET ; + uic_cmd.argument1 = attr_sel; + + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); + +if (mib_val) + *mib_val = uic_cmd.argument3; + +dev_dbg (hba->dev,"%s: error code %d\n" , get, ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_xxx_get); + +/** * ufshcd_make_hba_operational - Make UFS controller operational * @hba: per adapter instance *
@@ -1540,6 +1622,8 @@ static void ufshcd_uic_cmd_compl(struct ufs_hba *hba) { hba->active_uic_cmd->argument2 |=ufshcd_get_uic_cmd_result (hba); + hba->active_uic_cmd->argument3 = +ufshcd_get_dme_attr_val (hba);complete (&hba->active_uic_cmd->done); }
drivers/scsi/ufs/ufshcd.h +29 -0
@@ -217,4 +217,33 @@ int ufshcd_init(struct device *, struct ufs_hba ** , void __iomem * , unsigned int);void ufshcd_remove (struct ufs_hba *); +extern int ufshcd_dme_xxx_set (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val,u8 peer); +extern int ufshcd_dme_xxx_get (struct ufs_hba *hba,u32 attr_sel, +u32 *mib_val,u8 peer); + +static inline int ufshcd_dme_set (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val) +{ +return ufshcd_dme_xxx_set (hba, attr_sel, attr_set, mib_val,0 ); +} + +static inline int ufshcd_dme_peer_set (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val) +{ +return ufshcd_dme_xxx_set (hba, attr_sel, attr_set, mib_val,1 ); +} + +static inline int ufshcd_dme_get (struct ufs_hba *hba, +u32 attr_sel,u32 *mib_val) +{ +return ufshcd_dme_xxx_get (hba, attr_sel, mib_val,0 ); +} + +static inline int ufshcd_dme_peer_get (struct ufs_hba *hba, +u32 attr_sel,u32 *mib_val) +{ +return ufshcd_dme_xxx_get (hba, attr_sel, mib_val,1 ); +} +#endif /* End of Header */
drivers/scsi/ufs/ufshci.h +4 -0
@@ -191,6 +191,10 @@ enum {#define CONFIG_RESULT_CODE_MASK 0xFF#define GENERIC_ERROR_CODE_MASK 0xFF +#define UIC_ARG_MIB_SEL (attr, sel) ((((attr) & 0xFFFF) << 16) |\ + ((sel) & 0xFFFF)) +#define UIC_ARG_ATTR_SET (type) (((type) & 0xFF) << 16) +/* UIC Commands */ enum {UIC_CMD_DME_GET =0x01 ,
drivers/scsi/ufs/unipro.h new file +129 -0
129 lines not on this page · raw message
Signature · 1 line
1.7.0.4
Re: [PATCH v2 6/7] scsi: ufs: add dme configuration primitives
Quoted 325 lines
Implements to support Get and Set operation of the DME. And along with these operations, IDs of Attribute are added. It is used to configure the behavior of the UNIPRO.
Signed-off-by Seungwon Jeon <[email protected]>--- drivers/scsi/ufs/ufshcd.c | 84 +++++++++++++++++++++++++++++ drivers/scsi/ufs/ufshcd.h | 29 ++++++++++ drivers/scsi/ufs/ufshci.h | 4 ++ drivers/scsi/ufs/unipro.h | 129 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 246 insertions(+), 0 deletions(-) create mode 100644 drivers/scsi/ufs/unipro.hdrivers/scsi/ufs/ufshcd.c +1
-0@@ -191,6 +191,18 @@ static inline int ufshcd_get_uic_cmd_result(struct ufs_hba *hba) }/** +* ufshcd_get_dme_attr_val - Get the value of attribute returned by UIC command
+ * @hba: Pointer to adapter instance
+ *
+ * This function gets UIC command argument3
+ * Returns 0 on success, non zero value on error
+ */drivers/scsi/ufs/ufshcd.c +76
-0+static inline u32 ufshcd_get_dme_attr_val (struct ufs_hba *hba) +{ +return ufshcd_readl (hba,REG_UIC_COMMAND_ARG_3 ); +} + +/** * ufshcd_free_hba_memory - Free allocated memory for LRB, request * and task lists * @hba: Pointer to adapter instance @@ -1079,6 +1091,76 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba) }/** +* ufshcd_dme_xxx_set - UIC command for DME_SET, DME_PEER_SET +* @hba: per adapter instance +* @attr_sel: uic command argument1 +* @attr_set: attribute set type as uic command argument2 +* @mib_val: setting value as uic command argument3 +* @peer: indicate wherter peer or non-peer +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_xxx_set (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val,u8 peer) +{ +struct uic_command uic_cmd = {0 }; +static const char *const action[] = { +"dme-set" , +"dme-peer-set" + }; +const char *set = action[!!peer]; +int ret; + + uic_cmd.command = peer ? +UIC_CMD_DME_PEER_SET :UIC_CMD_DME_SET ; + uic_cmd.argument1 = attr_sel; + uic_cmd.argument2 =UIC_ARG_ATTR_SET (attr_set); + uic_cmd.argument3 = mib_val; + + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); + +dev_dbg (hba->dev,"%s: error code %d\n" , set, ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_xxx_set); + +/** +* ufshcd_dme_xxx_get - UIC command for DME_GET, DME_PEER_GET +* @hba: per adapter instance +* @attr_sel: uic command argument1 +* @mib_val: the value of the attribute as returned by the UIC command +* @peer: indicate wherter peer or non-peer +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_xxx_get (struct ufs_hba *hba,u32 attr_sel, +u32 *mib_val,u8 peer) +{ +struct uic_command uic_cmd = {0 }; +static const char *const action[] = { +"dme-get" , +"dme-peer-get" + }; +const char *get = action[!!peer]; +int ret; + + uic_cmd.command = peer ? +UIC_CMD_DME_PEER_GET :UIC_CMD_DME_GET ; + uic_cmd.argument1 = attr_sel; + + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); + +if (mib_val) + *mib_val = uic_cmd.argument3; + +dev_dbg (hba->dev,"%s: error code %d\n" , get, ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_xxx_get); + +/** * ufshcd_make_hba_operational - Make UFS controller operational * @hba: per adapter instance *
drivers/scsi/ufs/ufshcd.c +2
-0@@ -1540,6 +1622,8 @@ static void ufshcd_uic_cmd_compl(struct ufs_hba *hba) { hba->active_uic_cmd->argument2 |=ufshcd_get_uic_cmd_result (hba); + hba->active_uic_cmd->argument3 = +ufshcd_get_dme_attr_val (hba);complete (&hba->active_uic_cmd->done); }drivers/scsi/ufs/ufshcd.h +29
-0@@ -217,4 +217,33 @@ int ufshcd_init(struct device *, struct ufs_hba ** , void __iomem * , unsigned int);void ufshcd_remove (struct ufs_hba *); +extern int ufshcd_dme_xxx_set (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val,u8 peer); +extern int ufshcd_dme_xxx_get (struct ufs_hba *hba,u32 attr_sel, +u32 *mib_val,u8 peer); + +static inline int ufshcd_dme_set (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val) +{ +return ufshcd_dme_xxx_set (hba, attr_sel, attr_set, mib_val,0 ); +} + +static inline int ufshcd_dme_peer_set (struct ufs_hba *hba,u32 attr_sel, +u8 attr_set,u32 mib_val) +{ +return ufshcd_dme_xxx_set (hba, attr_sel, attr_set, mib_val,1 ); +} + +static inline int ufshcd_dme_get (struct ufs_hba *hba, +u32 attr_sel,u32 *mib_val) +{ +return ufshcd_dme_xxx_get (hba, attr_sel, mib_val,0 ); +} + +static inline int ufshcd_dme_peer_get (struct ufs_hba *hba, +u32 attr_sel,u32 *mib_val) +{ +return ufshcd_dme_xxx_get (hba, attr_sel, mib_val,1 ); +} +#endif /* End of Header */
drivers/scsi/ufs/ufshci.h +4
-0@@ -191,6 +191,10 @@ enum {#define CONFIG_RESULT_CODE_MASK 0xFF#define GENERIC_ERROR_CODE_MASK 0xFF +#define UIC_ARG_MIB_SEL (attr, sel) ((((attr) & 0xFFFF) << 16) |\ + ((sel) & 0xFFFF)) +#define UIC_ARG_ATTR_SET (type) (((type) & 0xFF) << 16) +/* UIC Commands */ enum {UIC_CMD_DME_GET =0x01 ,drivers/scsi/ufs/unipro.h new file +129
-1@@ -0,0 +1,129 @@ +/* +* drivers/scsi/ufs/unipro.h +* +* Copyright (C) 2013 Samsung Electronics Co., Ltd. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +*/ + +#ifndef _UNIPRO_H_ +#define _UNIPRO_H_ + +/* +* PHY Adpater attributes +*/ +#define PA_ACTIVETXDATALANES 0x1560 +#define PA_ACTIVERXDATALANES 0x1580 +#define PA_TXTRAILINGCLOCKS 0x1564 +#define PA_PHY_TYPE 0x1500 +#define PA_AVAILTXDATALANES 0x1520 +#define PA_AVAILRXDATALANES 0x1540 +#define PA_MINRXTRAILINGCLOCKS 0x1543 +#define PA_TXPWRSTATUS 0x1567 +#define PA_RXPWRSTATUS 0x1582 +#define PA_TXFORCECLOCK 0x1562 +#define PA_TXPWRMODE 0x1563 +#define PA_LEGACYDPHYESCDL 0x1570 +#define PA_MAXTXSPEEDFAST 0x1521 +#define PA_MAXTXSPEEDSLOW 0x1522 +#define PA_MAXRXSPEEDFAST 0x1541 +#define PA_MAXRXSPEEDSLOW 0x1542 +#define PA_TXLINKSTARTUPHS 0x1544 +#define PA_TXSPEEDFAST 0x1565 +#define PA_TXSPEEDSLOW 0x1566 +#define PA_REMOTEVERINFO 0x15A0 +#define PA_TXGEAR 0x1568 +#define PA_TXTERMINATION 0x1569 +#define PA_HSSERIES 0x156A +#define PA_PWRMODE 0x1571 +#define PA_RXGEAR 0x1583 +#define PA_RXTERMINATION 0x1584 +#define PA_MAXRXPWMGEAR 0x1586 +#define PA_MAXRXHSGEAR 0x1587 +#define PA_RXHSUNTERMCAP 0x15A5 +#define PA_RXLSTERMCAP 0x15A6 +#define PA_PACPREQTIMEOUT 0x1590 +#define PA_PACPREQEOBTIMEOUT 0x1591 +#define PA_LOCALVERINFO 0x15A9 +#define PA_TACTIVATE 0x15A8 +#define PA_PACPFRAMECOUNT 0x15C0 +#define PA_PACPERRORCOUNT 0x15C1 +#define PA_PHYTESTCONTROL 0x15C2 +#define PA_PWRMODEUSERDATA0 0x15B0 +#define PA_PWRMODEUSERDATA1 0x15B1 +#define PA_PWRMODEUSERDATA2 0x15B2 +#define PA_PWRMODEUSERDATA3 0x15B3 +#define PA_PWRMODEUSERDATA4 0x15B4 +#define PA_PWRMODEUSERDATA5 0x15B5 +#define PA_PWRMODEUSERDATA6 0x15B6 +#define PA_PWRMODEUSERDATA7 0x15B7 +#define PA_PWRMODEUSERDATA8 0x15B8 +#define PA_PWRMODEUSERDATA9 0x15B9 +#define PA_PWRMODEUSERDATA10 0x15BA +#define PA_PWRMODEUSERDATA11 0x15BB +#define PA_CONNECTEDTXDATALANE 0x1561 +#define PA_CONNECTEDRXDATALANE 0x1581 +#define PA_LOGICALLANEMAP 0x15A1 +#define PA_SLEEPNOCONFIGTIME 0x15A2 +#define PA_STALLNOCONFIGTIME 0x15A3 +#define PA_SAVECONFIGTIME 0x15A4 + +/* +* Data Link Layer Attributes +*/ +#define DL_TC0TXFCTHRESHOLD 0x2040 +#define DL_FC0PROTTIMEOUTVAL 0x2041 +#define DL_TC0REPLAYTIMEOUTVAL 0x2042 +#define DL_AFC0REQTIMEOUTVAL 0x2043 +#define DL_AFC0CREDITTHRESHOLD 0x2044 +#define DL_TC0OUTACKTHRESHOLD 0x2045 +#define DL_TC1TXFCTHRESHOLD 0x2060 +#define DL_FC1PROTTIMEOUTVAL 0x2061 +#define DL_TC1REPLAYTIMEOUTVAL 0x2062 +#define DL_AFC1REQTIMEOUTVAL 0x2063 +#define DL_AFC1CREDITTHRESHOLD 0x2064 +#define DL_TC1OUTACKTHRESHOLD 0x2065 +#define DL_TXPREEMPTIONCAP 0x2000 +#define DL_TC0TXMAXSDUSIZE 0x2001 +#define DL_TC0RXINITCREDITVAL 0x2002 +#define DL_TC0TXBUFFERSIZE 0x2005 +#define DL_PEERTC0PRESENT 0x2046 +#define DL_PEERTC0RXINITCREVAL 0x2047 +#define DL_TC1TXMAXSDUSIZE 0x2003 +#define DL_TC1RXINITCREDITVAL 0x2004 +#define DL_TC1TXBUFFERSIZE 0x2006 +#define DL_PEERTC1PRESENT 0x2066 +#define DL_PEERTC1RXINITCREVAL 0x2067 + +/* +* Network Layer Attributes +*/ +#define N_DEVICEID 0x3000 +#define N_DEVICEID_VALID 0x3001 +#define N_TC0TXMAXSDUSIZE 0x3020 +#define N_TC1TXMAXSDUSIZE 0x3021 + +/* +* Transport Layer Attributes +*/ +#define T_NUMCPORTS 0x4000 +#define T_NUMTESTFEATURES 0x4001 +#define T_CONNECTIONSTATE 0x4020 +#define T_PEERDEVICEID 0x4021 +#define T_PEERCPORTID 0x4022 +#define T_TRAFFICCLASS 0x4023 +#define T_PROTOCOLID 0x4024 +#define T_CPORTFLAGS 0x4025 +#define T_TXTOKENVALUE 0x4026 +#define T_RXTOKENVALUE 0x4027 +#define T_LOCALBUFFERSPACE 0x4028 +#define T_PEERBUFFERSPACE 0x4029 +#define T_CREDITSTOSEND 0x402A +#define T_CPORTMODE 0x402B +#define T_TC0TXMAXSDUSIZE 0x4060 +#define T_TC1TXMAXSDUSIZE 0x4061 + +#endif /* _UNIPRO_H_ */ --1.7.0.4
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 3 lines
Maya Erez QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
PATCH v2 7/7 scsi: ufs: add dme control primitives
In reply to Seungwon JeonImplements to support the following operations. Currently, this patch doesn't introduce DME_ENABLE and DME_RESET because host controller's HCE enable contains these roles.
DME_POWERON{OFF}, DME_HIBERNATE_ENTER{EXIT}, DME_ENDPOINTRESET.
--- drivers/scsi/ufs/ufshcd.c | 133 ++++++++++++++++++++++++++++++++++++++++++--- drivers/scsi/ufs/ufshcd.h | 26 +++++++++ drivers/scsi/ufs/ufshci.h | 15 +++++ 3 files changed, 166 insertions(+), 8 deletions(-)
drivers/scsi/ufs/ufshcd.c +125 -8
@@ -39,6 +39,7 @@#define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\ UTP_TASK_REQ_COMPL |\ + UFSHCD_HIBERNATE_MASK |\ UFSHCD_ERROR_MASK)/* UIC command timeout, unit: ms */ #define UIC_CMD_TIMEOUT 500
@@ -203,6 +204,18 @@ static inline u32 ufshcd_get_dme_attr_val(struct ufs_hba *hba) }/** +* ufshcd_get_upmcrs - Get the power mode change request status +* @hba: Pointer to adapter instance +* +* This function gets the UPMCRS field of HCS register +* Returns value of UPMCRS field +*/ +static inline u8 ufshcd_get_upmcrs (struct ufs_hba *hba) +{ +return (ufshcd_readl (hba,REG_CONTROLLER_STATUS ) >>8 ) &0x7 ; +} + +/** * ufshcd_free_hba_memory - Free allocated memory for LRB, request * and task lists * @hba: Pointer to adapter instance
@@ -1161,6 +1174,104 @@ int ufshcd_dme_xxx_get(struct ufs_hba *hba, u32 attr_sel,EXPORT_SYMBOL_GPL (ufshcd_dme_xxx_get);/** +* ufshcd_dme_power_xxx - UIC command for DME_POWERON, DME_POWEROFF +* @hba: per adapter instance +* @on: indicate wherter power_on or power_off +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_power_xxx (struct ufs_hba *hba,u8 on) +{ +struct uic_command uic_cmd = {0 }; +static const char *const action[] = { +"dme-power-off" , +"dme-power-on" + }; +const char *power = action[!!on]; +int ret; + + uic_cmd.command = on ? +UIC_CMD_DME_POWERON :UIC_CMD_DME_POWEROFF ; + + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) +dev_err (hba->dev,"%s: error code %d\n" , power, ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_power_xxx); + +/** +* ufshcd_dme_hibern8_xxx - UIC command for DME_HIBERNATE_ENTER, +* DME_HIBERNATE_EXIT +* @hba: per adapter instance +* @enter: indicate wherter hibernation enter or exit +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_hibern8_xxx (struct ufs_hba *hba,u8 enter) +{ +struct uic_command uic_cmd = {0 }; +static const char *const action[] = { +"dme-hibernate-exit" , +"dme-hibernate-enter" + }; +const char *hibern8 = action[!!enter]; +u8 status; +int ret; + + uic_cmd.command = enter ? +UIC_CMD_DME_HIBER_ENTER :UIC_CMD_DME_HIBER_EXIT ; + +mutex_lock (&hba->uic_cmd_mutex); + ret =__ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) { +dev_err (hba->dev,"%s: error code %d\n" , hibern8, ret); + goto out; + } + +init_completion (&hba->hibern8_done); + +if (wait_for_completion_timeout (&hba->hibern8_done, +msecs_to_jiffies (UIC_CMD_TIMEOUT ))) { + status =ufshcd_get_upmcrs (hba); +if (status !=PWR_LOCAL ) { +dev_err (hba->dev,"%s: failed, host upmcrs:%x\n" , + hibern8, status); + ret = status; + } + }else { +dev_err (hba->dev,"%s: timeout\n" , hibern8); + ret = -ETIMEDOUT ; + } +out: +mutex_unlock (&hba->uic_cmd_mutex); +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_hibern8_xxx); + +/** +* ufshcd_dme_endpt_reset - UIC command for DME_ENDPOINTRESET +* @hba: per adapter instance +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_endpt_reset (struct ufs_hba *hba) +{ +struct uic_command uic_cmd = {0 }; +int ret; + + uic_cmd.command =UIC_CMD_DME_END_PT_RST ; + + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) +dev_err (hba->dev,"endpoint reset: error code %d\n" , ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_endpt_reset); + +/** * ufshcd_make_hba_operational - Make UFS controller operational * @hba: per adapter instance *
@@ -1617,14 +1728,20 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)/** * ufshcd_uic_cmd_compl - handle completion of uic command * @hba: per adapter instance +* @intr_status: interrupt status generated by the controller */ -static void ufshcd_uic_cmd_compl (struct ufs_hba *hba) +static void ufshcd_uic_cmd_compl (struct ufs_hba *hba,u32 intr_status) { - hba->active_uic_cmd->argument2 |= -ufshcd_get_uic_cmd_result (hba); - hba->active_uic_cmd->argument3 = -ufshcd_get_dme_attr_val (hba); -complete (&hba->active_uic_cmd->done); +if (intr_status &UIC_COMMAND_COMPL ) { + hba->active_uic_cmd->argument2 |= +ufshcd_get_uic_cmd_result (hba); + hba->active_uic_cmd->argument3 = +ufshcd_get_dme_attr_val (hba); +complete (&hba->active_uic_cmd->done); + } + +if (intr_status &UFSHCD_HIBERNATE_MASK ) +complete (&hba->hibern8_done); }/**
@@ -1726,8 +1843,8 @@ static void ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status)if (hba->errors)ufshcd_err_handler (hba); -if (intr_status &UIC_COMMAND_COMPL ) -ufshcd_uic_cmd_compl (hba); +if (intr_status &UFSHCD_UIC_MASK ) +ufshcd_uic_cmd_compl (hba, intr_status);if (intr_status &UTP_TASK_REQ_COMPL )ufshcd_tmc_handler (hba);
drivers/scsi/ufs/ufshcd.h +26 -0
@@ -156,6 +156,7 @@ struct ufs_query {* @uic_cmd_mutex: mutex for uic command * @ufshcd_tm_wait_queue: wait queue for task management * @tm_condition: condition variable for task management +* @hibern8_done: completion for hibernate * @ufshcd_state: UFSHCD states * @intr_mask: Interrupt Mask Bits * @feh_workq: Work queue for fatal controller error handling
@@ -195,6 +196,8 @@ struct ufs_hba {wait_queue_head_t ufshcd_tm_wait_queue;unsigned long tm_condition; +struct completion hibern8_done; +u32 ufshcd_state;u32 intr_mask;
@@ -221,6 +224,9 @@ extern int ufshcd_dme_xxx_set(struct ufs_hba *hba, u32 attr_sel, u8 attr_set, u32 mib_val, u8 peer);extern int ufshcd_dme_xxx_get (struct ufs_hba *hba,u32 attr_sel,u32 *mib_val,u8 peer); +extern int ufshcd_dme_power_xxx (struct ufs_hba *hba,u8 on); +extern int ufshcd_dme_hibern8_xxx (struct ufs_hba *hba,u8 enter); +extern int ufshcd_dme_endpt_reset (struct ufs_hba *hba);static inline int ufshcd_dme_set (struct ufs_hba *hba,u32 attr_sel,u8 attr_set,u32 mib_val)
@@ -246,4 +252,24 @@ static inline int ufshcd_dme_peer_get(struct ufs_hba *hba, return ufshcd_dme_xxx_get(hba, attr_sel, mib_val, 1); } +static inline int ufshcd_dme_power_on (struct ufs_hba *hba) +{ +return ufshcd_dme_power_xxx (hba,1 ); +} + +static inline int ufshcd_dme_power_off (struct ufs_hba *hba) +{ +return ufshcd_dme_power_xxx (hba,0 ); +} + +static inline int ufshcd_dme_hibern8_enter (struct ufs_hba *hba) +{ +return ufshcd_dme_hibern8_xxx (hba,1 ); +} + +static inline int ufshcd_dme_hibern8_exit (struct ufs_hba *hba) +{ +return ufshcd_dme_hibern8_xxx (hba,0 ); +} +#endif /* End of Header */
drivers/scsi/ufs/ufshci.h +15 -0
@@ -124,6 +124,12 @@ enum {#define CONTROLLER_FATAL_ERROR UFS_BIT(16)#define SYSTEM_BUS_FATAL_ERROR UFS_BIT(17) +#define UFSHCD_HIBERNATE_MASK (UIC_HIBERNATE_ENTER |\ + UIC_HIBERNATE_EXIT) + +#define UFSHCD_UIC_MASK (UIC_COMMAND_COMPL |\ + UFSHCD_HIBERNATE_MASK) +#define UFSHCD_ERROR_MASK (UIC_ERROR |\ DEVICE_FATAL_ERROR |\ CONTROLLER_FATAL_ERROR |\
@@ -142,6 +148,15 @@ enum {#define DEVICE_ERROR_INDICATOR UFS_BIT(5)#define UIC_POWER_MODE_CHANGE_REQ_STATUS_MASK UFS_MASK(0x7, 8) +enum { +PWR_OK =0x0 , +PWR_LOCAL =0x01 , +PWR_REMOTE =0x02 , +PWR_BUSY =0x03 , +PWR_ERROR_CAP =0x04 , +PWR_FATAL_ERROR =0x05 , +}; +/* HCE - Host Controller Enable 34h */ #define CONTROLLER_ENABLE UFS_BIT(0)#define CONTROLLER_DISABLE 0x0
Signature · 1 line
1.7.0.4
Re: [PATCH v2 7/7] scsi: ufs: add dme control primitives
Quoted 45 lines · Seungwon Jeon
Implements to support the following operations. Currently, this patch doesn't introduce
DME_ENABLEandDME_RESETbecause host controller's HCE enable contains these roles.DME_POWERON{OFF}, DME_HIBERNATE_ENTER{EXIT},
DME_ENDPOINTRESET.Signed-off-by Seungwon Jeon <[email protected]>--- drivers/scsi/ufs/ufshcd.c | 133 ++++++++++++++++++++++++++++++++++++++++++--- drivers/scsi/ufs/ufshcd.h | 26 +++++++++ drivers/scsi/ufs/ufshci.h | 15 +++++ 3 files changed, 166 insertions(+), 8 deletions(-)drivers/scsi/ufs/ufshcd.c +13
-0@@ -39,6 +39,7 @@#define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\ UTP_TASK_REQ_COMPL |\ + UFSHCD_HIBERNATE_MASK |\ UFSHCD_ERROR_MASK)/* UIC command timeout, unit: ms */ #define UIC_CMD_TIMEOUT 500@@ -203,6 +204,18 @@ static inline u32 ufshcd_get_dme_attr_val(struct ufs_hba *hba) }/** +* ufshcd_get_upmcrs - Get the power mode change request status +* @hba: Pointer to adapter instance +* +* This function gets the UPMCRS field of HCS register +* Returns value of UPMCRS field +*/ +static inline u8 ufshcd_get_upmcrs (struct ufs_hba *hba) +{ +return (ufshcd_readl (hba,REG_CONTROLLER_STATUS ) >>8 ) &0x7 ; +} + +/** * ufshcd_free_hba_memory - Free allocated memory for LRB, request * and task lists * @hba: Pointer to adapter instance
drivers/scsi/ufs/ufshcd.c int ufshcd_dme_xxx_get(struct ufs_hba *hba, u32 attr_sel, · line 1183
Quoted 10 lines
drivers/scsi/ufs/ufshcd.c +7
-0@@ -1161,6 +1174,104 @@ int ufshcd_dme_xxx_get(struct ufs_hba *hba, u32 attr_sel,EXPORT_SYMBOL_GPL (ufshcd_dme_xxx_get);/** +* ufshcd_dme_power_xxx - UIC command for DME_POWERON, DME_POWEROFF +* @hba: per adapter instance +* @on: indicate wherter power_on or power_off +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_power_xxx (struct ufs_hba *hba,u8 on)
Instead of "xxx" can we have meaningful name like "switch" or "toggle"?
Quoted 40 lines
drivers/scsi/ufs/ufshcd.c +40
-0+{ +struct uic_command uic_cmd = {0 }; +static const char *const action[] = { +"dme-power-off" , +"dme-power-on" + }; +const char *power = action[!!on]; +int ret; + + uic_cmd.command = on ? +UIC_CMD_DME_POWERON :UIC_CMD_DME_POWEROFF ; + + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) +dev_err (hba->dev,"%s: error code %d\n" , power, ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_power_xxx); + +/** +* ufshcd_dme_hibern8_xxx - UIC command for DME_HIBERNATE_ENTER, +* DME_HIBERNATE_EXIT +* @hba: per adapter instance +* @enter: indicate wherter hibernation enter or exit +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_hibern8_xxx (struct ufs_hba *hba,u8 enter) +{ +struct uic_command uic_cmd = {0 }; +static const char *const action[] = { +"dme-hibernate-exit" , +"dme-hibernate-enter" + }; +const char *hibern8 = action[!!enter]; +u8 status; +int ret; + + uic_cmd.command = enter ?
drivers/scsi/ufs/ufshcd.c int ufshcd_dme_xxx_get(struct ufs_hba *hba, u32 attr_sel, · line 1233
Quoted 10 lines
drivers/scsi/ufs/ufshcd.c +10
-0+ UIC_CMD_DME_HIBER_ENTER :UIC_CMD_DME_HIBER_EXIT ; + +mutex_lock (&hba->uic_cmd_mutex); + ret =__ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) { +dev_err (hba->dev,"%s: error code %d\n" , hibern8, ret); + goto out; + } + +init_completion (&hba->hibern8_done);
Inititalizing here seems to be inappropriate, say you have back to back interrupts of UIC cmd and hibernate state enter/exit just before this init, there could be kernel crashes. Probably, you want to move this before sending uic cmd.
Quoted 172 lines
drivers/scsi/ufs/ufshcd.c +55
-8+ +if (wait_for_completion_timeout (&hba->hibern8_done, +msecs_to_jiffies (UIC_CMD_TIMEOUT ))) { + status =ufshcd_get_upmcrs (hba); +if (status !=PWR_LOCAL ) { +dev_err (hba->dev,"%s: failed, host upmcrs:%x\n" , + hibern8, status); + ret = status; + } + }else { +dev_err (hba->dev,"%s: timeout\n" , hibern8); + ret = -ETIMEDOUT ; + } +out: +mutex_unlock (&hba->uic_cmd_mutex); +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_hibern8_xxx); + +/** +* ufshcd_dme_endpt_reset - UIC command for DME_ENDPOINTRESET +* @hba: per adapter instance +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_endpt_reset (struct ufs_hba *hba) +{ +struct uic_command uic_cmd = {0 }; +int ret; + + uic_cmd.command =UIC_CMD_DME_END_PT_RST ; + + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) +dev_err (hba->dev,"endpoint reset: error code %d\n" , ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_endpt_reset); + +/** * ufshcd_make_hba_operational - Make UFS controller operational * @hba: per adapter instance * @@ -1617,14 +1728,20 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)/** * ufshcd_uic_cmd_compl - handle completion of uic command * @hba: per adapter instance +* @intr_status: interrupt status generated by the controller */ -static void ufshcd_uic_cmd_compl (struct ufs_hba *hba) +static void ufshcd_uic_cmd_compl (struct ufs_hba *hba,u32 intr_status) { - hba->active_uic_cmd->argument2 |= -ufshcd_get_uic_cmd_result (hba); - hba->active_uic_cmd->argument3 = -ufshcd_get_dme_attr_val (hba); -complete (&hba->active_uic_cmd->done); +if (intr_status &UIC_COMMAND_COMPL ) { + hba->active_uic_cmd->argument2 |= +ufshcd_get_uic_cmd_result (hba); + hba->active_uic_cmd->argument3 = +ufshcd_get_dme_attr_val (hba); +complete (&hba->active_uic_cmd->done); + } + +if (intr_status &UFSHCD_HIBERNATE_MASK ) +complete (&hba->hibern8_done); }/** @@ -1726,8 +1843,8 @@ static void ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status)if (hba->errors)ufshcd_err_handler (hba); -if (intr_status &UIC_COMMAND_COMPL ) -ufshcd_uic_cmd_compl (hba); +if (intr_status &UFSHCD_UIC_MASK ) +ufshcd_uic_cmd_compl (hba, intr_status);if (intr_status &UTP_TASK_REQ_COMPL )ufshcd_tmc_handler (hba);drivers/scsi/ufs/ufshcd.h +26
-0@@ -156,6 +156,7 @@ struct ufs_query {* @uic_cmd_mutex: mutex for uic command * @ufshcd_tm_wait_queue: wait queue for task management * @tm_condition: condition variable for task management +* @hibern8_done: completion for hibernate * @ufshcd_state: UFSHCD states * @intr_mask: Interrupt Mask Bits * @feh_workq: Work queue for fatal controller error handling @@ -195,6 +196,8 @@ struct ufs_hba {wait_queue_head_t ufshcd_tm_wait_queue;unsigned long tm_condition; +struct completion hibern8_done; +u32 ufshcd_state;u32 intr_mask;@@ -221,6 +224,9 @@ extern int ufshcd_dme_xxx_set(struct ufs_hba *hba, u32 attr_sel, u8 attr_set, u32 mib_val, u8 peer);extern int ufshcd_dme_xxx_get (struct ufs_hba *hba,u32 attr_sel,u32 *mib_val,u8 peer); +extern int ufshcd_dme_power_xxx (struct ufs_hba *hba,u8 on); +extern int ufshcd_dme_hibern8_xxx (struct ufs_hba *hba,u8 enter); +extern int ufshcd_dme_endpt_reset (struct ufs_hba *hba);static inline int ufshcd_dme_set (struct ufs_hba *hba,u32 attr_sel,u8 attr_set,u32 mib_val)@@ -246,4 +252,24 @@ static inline int ufshcd_dme_peer_get(struct ufs_hba *hba, return ufshcd_dme_xxx_get(hba, attr_sel, mib_val, 1); } +static inline int ufshcd_dme_power_on (struct ufs_hba *hba) +{ +return ufshcd_dme_power_xxx (hba,1 ); +} + +static inline int ufshcd_dme_power_off (struct ufs_hba *hba) +{ +return ufshcd_dme_power_xxx (hba,0 ); +} + +static inline int ufshcd_dme_hibern8_enter (struct ufs_hba *hba) +{ +return ufshcd_dme_hibern8_xxx (hba,1 ); +} + +static inline int ufshcd_dme_hibern8_exit (struct ufs_hba *hba) +{ +return ufshcd_dme_hibern8_xxx (hba,0 ); +} +#endif /* End of Header */ drivers/scsi/ufs/ufshci.h +15
-0@@ -124,6 +124,12 @@ enum {#define CONTROLLER_FATAL_ERROR UFS_BIT(16)#define SYSTEM_BUS_FATAL_ERROR UFS_BIT(17) +#define UFSHCD_HIBERNATE_MASK (UIC_HIBERNATE_ENTER |\ + UIC_HIBERNATE_EXIT) + +#define UFSHCD_UIC_MASK (UIC_COMMAND_COMPL |\ + UFSHCD_HIBERNATE_MASK) +#define UFSHCD_ERROR_MASK (UIC_ERROR |\ DEVICE_FATAL_ERROR |\ CONTROLLER_FATAL_ERROR |\@@ -142,6 +148,15 @@ enum {#define DEVICE_ERROR_INDICATOR UFS_BIT(5)#define UIC_POWER_MODE_CHANGE_REQ_STATUS_MASK UFS_MASK(0x7, 8) +enum { +PWR_OK =0x0 , +PWR_LOCAL =0x01 , +PWR_REMOTE =0x02 , +PWR_BUSY =0x03 , +PWR_ERROR_CAP =0x04 , +PWR_FATAL_ERROR =0x05 , +}; +/* HCE - Host Controller Enable 34h */ #define CONTROLLER_ENABLE UFS_BIT(0)#define CONTROLLER_DISABLE 0x0
Signature · 2 lines
Regards, Sujit
RE: [PATCH v2 7/7] scsi: ufs: add dme control primitives
Quoted 48 lines · Sujit Reddy Thumma
Quoted 47 lines · Seungwon Jeon
Implements to support the following operations. Currently, this patch doesn't introduce
DME_ENABLEandDME_RESETbecause host controller's HCE enable contains these roles.DME_POWERON{OFF}, DME_HIBERNATE_ENTER{EXIT},
DME_ENDPOINTRESET.Signed-off-by Seungwon Jeon <[email protected]>--- drivers/scsi/ufs/ufshcd.c | 133 ++++++++++++++++++++++++++++++++++++++++++--- drivers/scsi/ufs/ufshcd.h | 26 +++++++++ drivers/scsi/ufs/ufshci.h | 15 +++++ 3 files changed, 166 insertions(+), 8 deletions(-)drivers/scsi/ufs/ufshcd.c +13
-0@@ -39,6 +39,7 @@#define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\ UTP_TASK_REQ_COMPL |\ + UFSHCD_HIBERNATE_MASK |\ UFSHCD_ERROR_MASK)/* UIC command timeout, unit: ms */ #define UIC_CMD_TIMEOUT 500@@ -203,6 +204,18 @@ static inline u32 ufshcd_get_dme_attr_val(struct ufs_hba *hba) }/** +* ufshcd_get_upmcrs - Get the power mode change request status +* @hba: Pointer to adapter instance +* +* This function gets the UPMCRS field of HCS register +* Returns value of UPMCRS field +*/ +static inline u8 ufshcd_get_upmcrs (struct ufs_hba *hba) +{ +return (ufshcd_readl (hba,REG_CONTROLLER_STATUS ) >>8 ) &0x7 ; +} + +/** * ufshcd_free_hba_memory - Free allocated memory for LRB, request * and task lists * @hba: Pointer to adapter instance @@ -1161,6 +1174,104 @@ int ufshcd_dme_xxx_get(struct ufs_hba *hba, u32 attr_sel,EXPORT_SYMBOL_GPL (ufshcd_dme_xxx_get);
Quoted 9 lines
drivers/scsi/ufs/ufshcd.c int ufshcd_dme_xxx_get(struct ufs_hba *hba, u32 attr_sel, · line 1183
Quoted 8 lines
drivers/scsi/ufs/ufshcd.c +7
-0/** +* ufshcd_dme_power_xxx - UIC command for DME_POWERON, DME_POWEROFF +* @hba: per adapter instance +* @on: indicate wherter power_on or power_off +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_power_xxx (struct ufs_hba *hba,u8 on)Instead of "xxx" can we have meaningful name like "switch" or "toggle"?
It is just intended to express the standard's primitives name fully keeping intact. For actual usage, this function is wrapped like the followings.
static inline int ufshcd_dme_power_on(struct ufs_hba *hba)
{
return ufshcd_dme_power_xxx(hba, 1);
}static inline int ufshcd_dme_power_off(struct ufs_hba *hba)
{
return ufshcd_dme_power_xxx(hba, 0);
}Quoted 47 lines
Quoted 47 lines
drivers/scsi/ufs/ufshcd.c +46
-0+{ +struct uic_command uic_cmd = {0 }; +static const char *const action[] = { +"dme-power-off" , +"dme-power-on" + }; +const char *power = action[!!on]; +int ret; + + uic_cmd.command = on ? +UIC_CMD_DME_POWERON :UIC_CMD_DME_POWEROFF ; + + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) +dev_err (hba->dev,"%s: error code %d\n" , power, ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_power_xxx); + +/** +* ufshcd_dme_hibern8_xxx - UIC command for DME_HIBERNATE_ENTER, +* DME_HIBERNATE_EXIT +* @hba: per adapter instance +* @enter: indicate wherter hibernation enter or exit +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_hibern8_xxx (struct ufs_hba *hba,u8 enter) +{ +struct uic_command uic_cmd = {0 }; +static const char *const action[] = { +"dme-hibernate-exit" , +"dme-hibernate-enter" + }; +const char *hibern8 = action[!!enter]; +u8 status; +int ret; + + uic_cmd.command = enter ? +UIC_CMD_DME_HIBER_ENTER :UIC_CMD_DME_HIBER_EXIT ; + +mutex_lock (&hba->uic_cmd_mutex); + ret =__ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) { +dev_err (hba->dev,"%s: error code %d\n" , hibern8, ret);
Quoted 8 lines
drivers/scsi/ufs/ufshcd.c int ufshcd_dme_xxx_get(struct ufs_hba *hba, u32 attr_sel, · line 1233
Quoted 4 lines
drivers/scsi/ufs/ufshcd.c +4
-0+ goto out; + } + +init_completion (&hba->hibern8_done);Inititalizing here seems to be inappropriate, say you have back to back interrupts of UIC cmd and hibernate state enter/exit just before this init, there could be kernel crashes. Probably, you want to move this before sending uic cmd.
Yes, it makes sense.
If hibernation process is finished quickly after uic command is done, it should be considered. I'll apply it.
Thanks,
Seungwon Jeon
Quoted 181 lines
Quoted 163 lines
drivers/scsi/ufs/ufshcd.c +55
-8+ +if (wait_for_completion_timeout (&hba->hibern8_done, +msecs_to_jiffies (UIC_CMD_TIMEOUT ))) { + status =ufshcd_get_upmcrs (hba); +if (status !=PWR_LOCAL ) { +dev_err (hba->dev,"%s: failed, host upmcrs:%x\n" , + hibern8, status); + ret = status; + } + }else { +dev_err (hba->dev,"%s: timeout\n" , hibern8); + ret = -ETIMEDOUT ; + } +out: +mutex_unlock (&hba->uic_cmd_mutex); +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_hibern8_xxx); + +/** +* ufshcd_dme_endpt_reset - UIC command for DME_ENDPOINTRESET +* @hba: per adapter instance +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_endpt_reset (struct ufs_hba *hba) +{ +struct uic_command uic_cmd = {0 }; +int ret; + + uic_cmd.command =UIC_CMD_DME_END_PT_RST ; + + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) +dev_err (hba->dev,"endpoint reset: error code %d\n" , ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_endpt_reset); + +/** * ufshcd_make_hba_operational - Make UFS controller operational * @hba: per adapter instance * @@ -1617,14 +1728,20 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)/** * ufshcd_uic_cmd_compl - handle completion of uic command * @hba: per adapter instance +* @intr_status: interrupt status generated by the controller */ -static void ufshcd_uic_cmd_compl (struct ufs_hba *hba) +static void ufshcd_uic_cmd_compl (struct ufs_hba *hba,u32 intr_status) { - hba->active_uic_cmd->argument2 |= -ufshcd_get_uic_cmd_result (hba); - hba->active_uic_cmd->argument3 = -ufshcd_get_dme_attr_val (hba); -complete (&hba->active_uic_cmd->done); +if (intr_status &UIC_COMMAND_COMPL ) { + hba->active_uic_cmd->argument2 |= +ufshcd_get_uic_cmd_result (hba); + hba->active_uic_cmd->argument3 = +ufshcd_get_dme_attr_val (hba); +complete (&hba->active_uic_cmd->done); + } + +if (intr_status &UFSHCD_HIBERNATE_MASK ) +complete (&hba->hibern8_done); }/** @@ -1726,8 +1843,8 @@ static void ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status)if (hba->errors)ufshcd_err_handler (hba); -if (intr_status &UIC_COMMAND_COMPL ) -ufshcd_uic_cmd_compl (hba); +if (intr_status &UFSHCD_UIC_MASK ) +ufshcd_uic_cmd_compl (hba, intr_status);if (intr_status &UTP_TASK_REQ_COMPL )ufshcd_tmc_handler (hba);drivers/scsi/ufs/ufshcd.h +26
-0@@ -156,6 +156,7 @@ struct ufs_query {* @uic_cmd_mutex: mutex for uic command * @ufshcd_tm_wait_queue: wait queue for task management * @tm_condition: condition variable for task management +* @hibern8_done: completion for hibernate * @ufshcd_state: UFSHCD states * @intr_mask: Interrupt Mask Bits * @feh_workq: Work queue for fatal controller error handling @@ -195,6 +196,8 @@ struct ufs_hba {wait_queue_head_t ufshcd_tm_wait_queue;unsigned long tm_condition; +struct completion hibern8_done; +u32 ufshcd_state;u32 intr_mask;@@ -221,6 +224,9 @@ extern int ufshcd_dme_xxx_set(struct ufs_hba *hba, u32 attr_sel, u8 attr_set, u32 mib_val, u8 peer);extern int ufshcd_dme_xxx_get (struct ufs_hba *hba,u32 attr_sel,u32 *mib_val,u8 peer); +extern int ufshcd_dme_power_xxx (struct ufs_hba *hba,u8 on); +extern int ufshcd_dme_hibern8_xxx (struct ufs_hba *hba,u8 enter); +extern int ufshcd_dme_endpt_reset (struct ufs_hba *hba);static inline int ufshcd_dme_set (struct ufs_hba *hba,u32 attr_sel,u8 attr_set,u32 mib_val)@@ -246,4 +252,24 @@ static inline int ufshcd_dme_peer_get(struct ufs_hba *hba, return ufshcd_dme_xxx_get(hba, attr_sel, mib_val, 1); } +static inline int ufshcd_dme_power_on (struct ufs_hba *hba) +{ +return ufshcd_dme_power_xxx (hba,1 ); +} + +static inline int ufshcd_dme_power_off (struct ufs_hba *hba) +{ +return ufshcd_dme_power_xxx (hba,0 ); +} + +static inline int ufshcd_dme_hibern8_enter (struct ufs_hba *hba) +{ +return ufshcd_dme_hibern8_xxx (hba,1 ); +} + +static inline int ufshcd_dme_hibern8_exit (struct ufs_hba *hba) +{ +return ufshcd_dme_hibern8_xxx (hba,0 ); +} +#endif /* End of Header */ drivers/scsi/ufs/ufshci.h +8
-0@@ -124,6 +124,12 @@ enum {#define CONTROLLER_FATAL_ERROR UFS_BIT(16)#define SYSTEM_BUS_FATAL_ERROR UFS_BIT(17) +#define UFSHCD_HIBERNATE_MASK (UIC_HIBERNATE_ENTER |\ + UIC_HIBERNATE_EXIT) + +#define UFSHCD_UIC_MASK (UIC_COMMAND_COMPL |\ + UFSHCD_HIBERNATE_MASK) +#define UFSHCD_ERROR_MASK (UIC_ERROR |\ DEVICE_FATAL_ERROR |\ CONTROLLER_FATAL_ERROR |\@@ -142,6 +148,15 @@ enum {#define DEVICE_ERROR_INDICATOR UFS_BIT(5)#define UIC_POWER_MODE_CHANGE_REQ_STATUS_MASK UFS_MASK(0x7, 8) +enum { +PWR_OK =0x0 ,drivers/scsi/ufs/ufshci.h enum { · line 162
Quoted 10 lines
drivers/scsi/ufs/ufshci.h +7
-0+PWR_LOCAL =0x01 , +PWR_REMOTE =0x02 , +PWR_BUSY =0x03 , +PWR_ERROR_CAP =0x04 , + PWR_FATAL_ERROR = 0x05, +}; +/* HCE - Host Controller Enable 34h */ #define CONTROLLER_ENABLE UFS_BIT(0)#define CONTROLLER_DISABLE 0x0--
Regards,
Sujit
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 7/7] scsi: ufs: add dme control primitives
In reply to Seungwon JeonQuoted 292 lines
Implements to support the following operations. Currently, this patch doesn't introduce
DME_ENABLEandDME_RESETbecause host controller's HCE enable contains these roles.DME_POWERON{OFF}, DME_HIBERNATE_ENTER{EXIT},
DME_ENDPOINTRESET.Signed-off-by Seungwon Jeon <[email protected]>--- drivers/scsi/ufs/ufshcd.c | 133 ++++++++++++++++++++++++++++++++++++++++++--- drivers/scsi/ufs/ufshcd.h | 26 +++++++++ drivers/scsi/ufs/ufshci.h | 15 +++++ 3 files changed, 166 insertions(+), 8 deletions(-)drivers/scsi/ufs/ufshcd.c +13
-0@@ -39,6 +39,7 @@#define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\ UTP_TASK_REQ_COMPL |\ + UFSHCD_HIBERNATE_MASK |\ UFSHCD_ERROR_MASK)/* UIC command timeout, unit: ms */ #define UIC_CMD_TIMEOUT 500@@ -203,6 +204,18 @@ static inline u32 ufshcd_get_dme_attr_val(struct ufs_hba *hba) }/** +* ufshcd_get_upmcrs - Get the power mode change request status +* @hba: Pointer to adapter instance +* +* This function gets the UPMCRS field of HCS register +* Returns value of UPMCRS field +*/ +static inline u8 ufshcd_get_upmcrs (struct ufs_hba *hba) +{ +return (ufshcd_readl (hba,REG_CONTROLLER_STATUS ) >>8 ) &0x7 ; +} + +/** * ufshcd_free_hba_memory - Free allocated memory for LRB, request * and task lists * @hba: Pointer to adapter instance
drivers/scsi/ufs/ufshcd.c +98
-0@@ -1161,6 +1174,104 @@ int ufshcd_dme_xxx_get(struct ufs_hba *hba, u32 attr_sel,EXPORT_SYMBOL_GPL (ufshcd_dme_xxx_get);/** +* ufshcd_dme_power_xxx - UIC command for DME_POWERON, DME_POWEROFF +* @hba: per adapter instance +* @on: indicate wherter power_on or power_off +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_power_xxx (struct ufs_hba *hba,u8 on) +{ +struct uic_command uic_cmd = {0 }; +static const char *const action[] = { +"dme-power-off" , +"dme-power-on" + }; +const char *power = action[!!on]; +int ret; + + uic_cmd.command = on ? +UIC_CMD_DME_POWERON :UIC_CMD_DME_POWEROFF ; + + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) +dev_err (hba->dev,"%s: error code %d\n" , power, ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_power_xxx); + +/** +* ufshcd_dme_hibern8_xxx - UIC command for DME_HIBERNATE_ENTER, +* DME_HIBERNATE_EXIT +* @hba: per adapter instance +* @enter: indicate wherter hibernation enter or exit +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_hibern8_xxx (struct ufs_hba *hba,u8 enter) +{ +struct uic_command uic_cmd = {0 }; +static const char *const action[] = { +"dme-hibernate-exit" , +"dme-hibernate-enter" + }; +const char *hibern8 = action[!!enter]; +u8 status; +int ret; + + uic_cmd.command = enter ? +UIC_CMD_DME_HIBER_ENTER :UIC_CMD_DME_HIBER_EXIT ; + +mutex_lock (&hba->uic_cmd_mutex); + ret =__ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) { +dev_err (hba->dev,"%s: error code %d\n" , hibern8, ret); + goto out; + } + +init_completion (&hba->hibern8_done); + +if (wait_for_completion_timeout (&hba->hibern8_done, +msecs_to_jiffies (UIC_CMD_TIMEOUT ))) { + status =ufshcd_get_upmcrs (hba); +if (status !=PWR_LOCAL ) { +dev_err (hba->dev,"%s: failed, host upmcrs:%x\n" , + hibern8, status); + ret = status; + } + }else { +dev_err (hba->dev,"%s: timeout\n" , hibern8); + ret = -ETIMEDOUT ; + } +out: +mutex_unlock (&hba->uic_cmd_mutex); +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_hibern8_xxx); + +/** +* ufshcd_dme_endpt_reset - UIC command for DME_ENDPOINTRESET +* @hba: per adapter instance +* +* Returns 0 on success, non-zero value on failure +*/ +int ufshcd_dme_endpt_reset (struct ufs_hba *hba) +{ +struct uic_command uic_cmd = {0 }; +int ret; + + uic_cmd.command =UIC_CMD_DME_END_PT_RST ; + + ret =ufshcd_send_uic_cmd (hba, &uic_cmd); +if (ret) +dev_err (hba->dev,"endpoint reset: error code %d\n" , ret); + +return ret; +} +EXPORT_SYMBOL_GPL (ufshcd_dme_endpt_reset); + +/** * ufshcd_make_hba_operational - Make UFS controller operational * @hba: per adapter instance *
drivers/scsi/ufs/ufshcd.c +12
-6@@ -1617,14 +1728,20 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)/** * ufshcd_uic_cmd_compl - handle completion of uic command * @hba: per adapter instance +* @intr_status: interrupt status generated by the controller */ -static void ufshcd_uic_cmd_compl (struct ufs_hba *hba) +static void ufshcd_uic_cmd_compl (struct ufs_hba *hba,u32 intr_status) { - hba->active_uic_cmd->argument2 |= -ufshcd_get_uic_cmd_result (hba); - hba->active_uic_cmd->argument3 = -ufshcd_get_dme_attr_val (hba); -complete (&hba->active_uic_cmd->done); +if (intr_status &UIC_COMMAND_COMPL ) { + hba->active_uic_cmd->argument2 |= +ufshcd_get_uic_cmd_result (hba); + hba->active_uic_cmd->argument3 = +ufshcd_get_dme_attr_val (hba); +complete (&hba->active_uic_cmd->done); + } + +if (intr_status &UFSHCD_HIBERNATE_MASK ) +complete (&hba->hibern8_done); }/**
drivers/scsi/ufs/ufshcd.c +2
-2@@ -1726,8 +1843,8 @@ static void ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status)if (hba->errors)ufshcd_err_handler (hba); -if (intr_status &UIC_COMMAND_COMPL ) -ufshcd_uic_cmd_compl (hba); +if (intr_status &UFSHCD_UIC_MASK ) +ufshcd_uic_cmd_compl (hba, intr_status);if (intr_status &UTP_TASK_REQ_COMPL )drivers/scsi/ufs/ufshcd.c +0
-0ufshcd_tmc_handler (hba);drivers/scsi/ufs/ufshcd.h +6
-0@@ -156,6 +156,7 @@ struct ufs_query {* @uic_cmd_mutex: mutex for uic command * @ufshcd_tm_wait_queue: wait queue for task management * @tm_condition: condition variable for task management +* @hibern8_done: completion for hibernate * @ufshcd_state: UFSHCD states * @intr_mask: Interrupt Mask Bits * @feh_workq: Work queue for fatal controller error handling @@ -195,6 +196,8 @@ struct ufs_hba {wait_queue_head_t ufshcd_tm_wait_queue;unsigned long tm_condition; +struct completion hibern8_done; +u32 ufshcd_state;u32 intr_mask;@@ -221,6 +224,9 @@ extern int ufshcd_dme_xxx_set(struct ufs_hba *hba, u32 attr_sel, u8 attr_set, u32 mib_val, u8 peer);extern int ufshcd_dme_xxx_get (struct ufs_hba *hba,u32 attr_sel,u32 *mib_val,u8 peer); +extern int ufshcd_dme_power_xxx (struct ufs_hba *hba,u8 on); +extern int ufshcd_dme_hibern8_xxx (struct ufs_hba *hba,u8 enter); +extern int ufshcd_dme_endpt_reset (struct ufs_hba *hba); static inline int ufshcd_dme_set(struct ufs_hba *hba, u32 attr_sel,drivers/scsi/ufs/ufshcd.h +20
-0u8 attr_set, u32 mib_val)@@ -246,4 +252,24 @@ static inline int ufshcd_dme_peer_get(struct ufs_hba *hba, return ufshcd_dme_xxx_get(hba, attr_sel, mib_val, 1); } +static inline int ufshcd_dme_power_on (struct ufs_hba *hba) +{ +return ufshcd_dme_power_xxx (hba,1 ); +} + +static inline int ufshcd_dme_power_off (struct ufs_hba *hba) +{ +return ufshcd_dme_power_xxx (hba,0 ); +} + +static inline int ufshcd_dme_hibern8_enter (struct ufs_hba *hba) +{ +return ufshcd_dme_hibern8_xxx (hba,1 ); +} + +static inline int ufshcd_dme_hibern8_exit (struct ufs_hba *hba) +{ +return ufshcd_dme_hibern8_xxx (hba,0 ); +} +#endif /* End of Header */
drivers/scsi/ufs/ufshci.h +15
-1@@ -124,6 +124,12 @@ enum {#define CONTROLLER_FATAL_ERROR UFS_BIT(16)#define SYSTEM_BUS_FATAL_ERROR UFS_BIT(17) +#define UFSHCD_HIBERNATE_MASK (UIC_HIBERNATE_ENTER |\ + UIC_HIBERNATE_EXIT) + +#define UFSHCD_UIC_MASK (UIC_COMMAND_COMPL |\ + UFSHCD_HIBERNATE_MASK) +#define UFSHCD_ERROR_MASK (UIC_ERROR |\ DEVICE_FATAL_ERROR |\ CONTROLLER_FATAL_ERROR |\@@ -142,6 +148,15 @@ enum {#define DEVICE_ERROR_INDICATOR UFS_BIT(5)#define UIC_POWER_MODE_CHANGE_REQ_STATUS_MASK UFS_MASK(0x7, 8) +enum { +PWR_OK =0x0 , +PWR_LOCAL =0x01 , +PWR_REMOTE =0x02 , +PWR_BUSY =0x03 , +PWR_ERROR_CAP =0x04 , +PWR_FATAL_ERROR =0x05 , +}; +/* HCE - Host Controller Enable 34h */ #define CONTROLLER_ENABLE UFS_BIT(0)#define CONTROLLER_DISABLE 0x0 --1.7.0.4
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 3 lines
Maya Erez QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation