Commit 2fbd009b authored by Seungwon Jeon's avatar Seungwon Jeon Committed by James Bottomley

[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: default avatarSeungwon Jeon <tgih.jun@samsung.com>
Tested-by: default avatarMaya Erez <merez@codeaurora.org>
Signed-off-by: default avatarSantosh Y <santoshsy@gmail.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent b873a275
...@@ -35,6 +35,10 @@ ...@@ -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 { ...@@ -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) ...@@ -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); ufshcd_writel(hba, set, REG_INTERRUPT_ENABLE);
break; }
/**
* 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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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,
}; };
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment