[SCSI] ufs: amend interrupt configuration
It makes interrupt setting more flexible especially for disabling. And wrong bit mask is fixed for ver 1.0. [17:16] is added for mask. Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com> Tested-by: Maya Erez <merez@codeaurora.org> Signed-off-by: Santosh Y <santoshsy@gmail.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
This commit is contained in:
parent
b873a27538
commit
2fbd009b40
@ -35,6 +35,10 @@
|
|||||||
|
|
||||||
#include "ufshcd.h"
|
#include "ufshcd.h"
|
||||||
|
|
||||||
|
#define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\
|
||||||
|
UTP_TASK_REQ_COMPL |\
|
||||||
|
UFSHCD_ERROR_MASK)
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
UFSHCD_MAX_CHANNEL = 0,
|
UFSHCD_MAX_CHANNEL = 0,
|
||||||
UFSHCD_MAX_ID = 1,
|
UFSHCD_MAX_ID = 1,
|
||||||
@ -63,6 +67,20 @@ enum {
|
|||||||
INT_AGGR_CONFIG,
|
INT_AGGR_CONFIG,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ufshcd_get_intr_mask - Get the interrupt bit mask
|
||||||
|
* @hba - Pointer to adapter instance
|
||||||
|
*
|
||||||
|
* Returns interrupt bit mask per version
|
||||||
|
*/
|
||||||
|
static inline u32 ufshcd_get_intr_mask(struct ufs_hba *hba)
|
||||||
|
{
|
||||||
|
if (hba->ufs_version == UFSHCI_VERSION_10)
|
||||||
|
return INTERRUPT_MASK_ALL_VER_10;
|
||||||
|
else
|
||||||
|
return INTERRUPT_MASK_ALL_VER_11;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ufshcd_get_ufs_version - Get the UFS version supported by the HBA
|
* ufshcd_get_ufs_version - Get the UFS version supported by the HBA
|
||||||
* @hba - Pointer to adapter instance
|
* @hba - Pointer to adapter instance
|
||||||
@ -389,25 +407,45 @@ static int ufshcd_map_sg(struct ufshcd_lrb *lrbp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ufshcd_int_config - enable/disable interrupts
|
* ufshcd_enable_intr - enable interrupts
|
||||||
* @hba: per adapter instance
|
* @hba: per adapter instance
|
||||||
* @option: interrupt option
|
* @intrs: interrupt bits
|
||||||
*/
|
*/
|
||||||
static void ufshcd_int_config(struct ufs_hba *hba, u32 option)
|
static void ufshcd_enable_intr(struct ufs_hba *hba, u32 intrs)
|
||||||
{
|
{
|
||||||
switch (option) {
|
u32 set = ufshcd_readl(hba, REG_INTERRUPT_ENABLE);
|
||||||
case UFSHCD_INT_ENABLE:
|
|
||||||
ufshcd_writel(hba, hba->int_enable_mask, REG_INTERRUPT_ENABLE);
|
if (hba->ufs_version == UFSHCI_VERSION_10) {
|
||||||
break;
|
u32 rw;
|
||||||
case UFSHCD_INT_DISABLE:
|
rw = set & INTERRUPT_MASK_RW_VER_10;
|
||||||
if (hba->ufs_version == UFSHCI_VERSION_10)
|
set = rw | ((set ^ intrs) & intrs);
|
||||||
ufshcd_writel(hba, INTERRUPT_DISABLE_MASK_10,
|
} else {
|
||||||
REG_INTERRUPT_ENABLE);
|
set |= intrs;
|
||||||
else
|
|
||||||
ufshcd_writel(hba, INTERRUPT_DISABLE_MASK_11,
|
|
||||||
REG_INTERRUPT_ENABLE);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ufshcd_writel(hba, set, REG_INTERRUPT_ENABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ufshcd_disable_intr - disable interrupts
|
||||||
|
* @hba: per adapter instance
|
||||||
|
* @intrs: interrupt bits
|
||||||
|
*/
|
||||||
|
static void ufshcd_disable_intr(struct ufs_hba *hba, u32 intrs)
|
||||||
|
{
|
||||||
|
u32 set = ufshcd_readl(hba, REG_INTERRUPT_ENABLE);
|
||||||
|
|
||||||
|
if (hba->ufs_version == UFSHCI_VERSION_10) {
|
||||||
|
u32 rw;
|
||||||
|
rw = (set & INTERRUPT_MASK_RW_VER_10) &
|
||||||
|
~(intrs & INTERRUPT_MASK_RW_VER_10);
|
||||||
|
set = rw | ((set & intrs) & ~INTERRUPT_MASK_RW_VER_10);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
set &= ~intrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
ufshcd_writel(hba, set, REG_INTERRUPT_ENABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -709,8 +747,7 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba)
|
|||||||
uic_cmd->argument3 = 0;
|
uic_cmd->argument3 = 0;
|
||||||
|
|
||||||
/* enable UIC related interrupts */
|
/* enable UIC related interrupts */
|
||||||
hba->int_enable_mask |= UIC_COMMAND_COMPL;
|
ufshcd_enable_intr(hba, UIC_COMMAND_COMPL);
|
||||||
ufshcd_int_config(hba, UFSHCD_INT_ENABLE);
|
|
||||||
|
|
||||||
/* sending UIC commands to controller */
|
/* sending UIC commands to controller */
|
||||||
ufshcd_send_uic_command(hba, uic_cmd);
|
ufshcd_send_uic_command(hba, uic_cmd);
|
||||||
@ -757,13 +794,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Enable required interrupts */
|
/* Enable required interrupts */
|
||||||
hba->int_enable_mask |= (UTP_TRANSFER_REQ_COMPL |
|
ufshcd_enable_intr(hba, UFSHCD_ENABLE_INTRS);
|
||||||
UIC_ERROR |
|
|
||||||
UTP_TASK_REQ_COMPL |
|
|
||||||
DEVICE_FATAL_ERROR |
|
|
||||||
CONTROLLER_FATAL_ERROR |
|
|
||||||
SYSTEM_BUS_FATAL_ERROR);
|
|
||||||
ufshcd_int_config(hba, UFSHCD_INT_ENABLE);
|
|
||||||
|
|
||||||
/* Configure interrupt aggregation */
|
/* Configure interrupt aggregation */
|
||||||
ufshcd_config_int_aggr(hba, INT_AGGR_CONFIG);
|
ufshcd_config_int_aggr(hba, INT_AGGR_CONFIG);
|
||||||
@ -1570,7 +1601,7 @@ static void ufshcd_hba_free(struct ufs_hba *hba)
|
|||||||
void ufshcd_remove(struct ufs_hba *hba)
|
void ufshcd_remove(struct ufs_hba *hba)
|
||||||
{
|
{
|
||||||
/* disable interrupts */
|
/* disable interrupts */
|
||||||
ufshcd_int_config(hba, UFSHCD_INT_DISABLE);
|
ufshcd_disable_intr(hba, hba->intr_mask);
|
||||||
|
|
||||||
ufshcd_hba_stop(hba);
|
ufshcd_hba_stop(hba);
|
||||||
ufshcd_hba_free(hba);
|
ufshcd_hba_free(hba);
|
||||||
@ -1628,6 +1659,9 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle,
|
|||||||
/* Get UFS version supported by the controller */
|
/* Get UFS version supported by the controller */
|
||||||
hba->ufs_version = ufshcd_get_ufs_version(hba);
|
hba->ufs_version = ufshcd_get_ufs_version(hba);
|
||||||
|
|
||||||
|
/* Get Interrupt bit mask per version */
|
||||||
|
hba->intr_mask = ufshcd_get_intr_mask(hba);
|
||||||
|
|
||||||
/* Allocate memory for host memory space */
|
/* Allocate memory for host memory space */
|
||||||
err = ufshcd_memory_alloc(hba);
|
err = ufshcd_memory_alloc(hba);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -139,7 +139,7 @@ struct ufshcd_lrb {
|
|||||||
* @ufshcd_tm_wait_queue: wait queue for task management
|
* @ufshcd_tm_wait_queue: wait queue for task management
|
||||||
* @tm_condition: condition variable for task management
|
* @tm_condition: condition variable for task management
|
||||||
* @ufshcd_state: UFSHCD states
|
* @ufshcd_state: UFSHCD states
|
||||||
* @int_enable_mask: Interrupt Mask Bits
|
* @intr_mask: Interrupt Mask Bits
|
||||||
* @uic_workq: Work queue for UIC completion handling
|
* @uic_workq: Work queue for UIC completion handling
|
||||||
* @feh_workq: Work queue for fatal controller error handling
|
* @feh_workq: Work queue for fatal controller error handling
|
||||||
* @errors: HBA errors
|
* @errors: HBA errors
|
||||||
@ -176,7 +176,7 @@ struct ufs_hba {
|
|||||||
unsigned long tm_condition;
|
unsigned long tm_condition;
|
||||||
|
|
||||||
u32 ufshcd_state;
|
u32 ufshcd_state;
|
||||||
u32 int_enable_mask;
|
u32 intr_mask;
|
||||||
|
|
||||||
/* Work Queues */
|
/* Work Queues */
|
||||||
struct work_struct uic_workq;
|
struct work_struct uic_workq;
|
||||||
|
@ -232,10 +232,11 @@ enum {
|
|||||||
/* Interrupt disable masks */
|
/* Interrupt disable masks */
|
||||||
enum {
|
enum {
|
||||||
/* Interrupt disable mask for UFSHCI v1.0 */
|
/* Interrupt disable mask for UFSHCI v1.0 */
|
||||||
INTERRUPT_DISABLE_MASK_10 = 0xFFFF,
|
INTERRUPT_MASK_ALL_VER_10 = 0x30FFF,
|
||||||
|
INTERRUPT_MASK_RW_VER_10 = 0x30000,
|
||||||
|
|
||||||
/* Interrupt disable mask for UFSHCI v1.1 */
|
/* Interrupt disable mask for UFSHCI v1.1 */
|
||||||
INTERRUPT_DISABLE_MASK_11 = 0x0,
|
INTERRUPT_MASK_ALL_VER_11 = 0x31FFF,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user